J2EE / JBoss

mmoossen
14 de Febrero del 2002
Que tal si se arma un foro para j2ee, ya sea en general o directamente orientado al sevidor de aplicaciones gratuito JBoss...

maratna
14 de Febrero del 2002
No estaría mal

maratna
14 de Febrero del 2002
¿Se puede con un CMP de entidad hacer que con un findByprimaryKey te haga una select y te devuelva ese resultset?
La verdad es que yo solo uso los CMP de entidad para insertar, borrar o actualizar registros de uno en uno, y me gustaria poder hacerlo mediante una select, update o delete como en JDBC.

raularranz
14 de Febrero del 2002
tendrías que usar los BMP
te mando un código con sus aclaraciones:


Persistencia Controlada por el Bean

En un bean enterprise con la persistencia manejada por el Bean (BMP) maneja la sincronización de su estado con la base de datos directamente . El Bean usa el API de bases de datos (normalmente JDBC) para leer y escribir sus campos en la base de datos, pero el contenedor le dice cuando hacer cada operación de sincronización y maneja las transaciones por el bean automáticamente. La persistencia manejada por el bean le da al desarrollador de bean la flexibilidad de realizar operaciones de persistencia que son demasiado complicadas para el contenedor o para usar una fuente de datos que no está soportada por el contenedor -- por ejemplo bases de datos legales y personalizadas.
En esta sección, modificaremos la clase CustomerBean para crear un bean con persistencia manejada por el Bean (BMP). Esta modificación no impactará en absoluto en los interfaces home o remoto. De hecho, no modificaremos directamente el CustomerBean original. En su lugar, lo cambiaremos a persistencia manejada por el bean extendiendo el bean y sobreescribiendo la clase para crear una entidad BMP. En la mayoría de los casos, no extenderemos el bean para hacerlo BMP, sólo implementaremos el bean como BMP directamente. Esta estrategia (extender el bean CMP) se hace por dos razones: permite al bean ser un bean CMP o BMP; y acorta significativamente la cantidad de código a mostrar. Abajo tenemos la definición de la clase BMP.

public class CustomerBean_BMP extends CustomerBean {
public void ejbLoad() {
// override implementation
}
public void ejbStore() {
// override implementation
}
public void ejbCreate() {
// override implementation
}
public void ejbRemove() {
// override implementation
}
private Connection getConnection() {
// new helper method
}
}

Con beans BMP, los métodos ejbLoad() y ejbStore() los usa el contenedor de forma diferente a como lo hacía con un bean CMP. En BMP, estos métodos contienen código para leer los datos de la base de datos y para escribir los cambios en la base de datos, respectivamente. Estos métodos se llaman sobre el bean cuando el servidor EJB decide que es un buen momento para leer o escribir los datos.
El bean CustomerBean_BMP maneja su propia persistencia. En otras palabras, los métodos ejbLoad() y ejbStore() deben incluir lógica de acceso a base de datos para que el bean pueda cargar y almacenar sus datos cuando el contenedor EJB se lo diga. El contenedor ejecutará automátiamente los métodos ejbLoad() y ejbStore() cuando crea apropiado.
El método ejbLoad() se invoca normalmente al principio de una transación, justo antes de que el contenedor delege un método de negocio del bean. El código mostrado abajo muestra cómo implementar el método ejbLoad() usando JDBC.

import java.sql.Connection;

public class CustomerBean_BMP extends CustomerBean {

public void ejbLoad() {
Connection con;
try {
Integer primaryKey =
(Integer)ejbContext.getPrimaryKey();
con = this.getConnection();
Statement sqlStmt = con.createStatement("SELECT * FROM Customer " + " WHERE customerID = "
+ primaryKey.intValue());
ResultSet results = sqlStmt.executeQuery();
if (results.next()) {
// get the name information
//from the customer table
myName = new Name();
myName.first = results.getString("FIRST_NAME");
myName.last = results.getString("LAST_NAME");
myName.middle = results.getString("MIDDLE_NAME");
// get the address information from
//the customer table
myAddress = new Address();
myAddress.street =
results.getString("STREET");
myAddress.city =
results.getString("CITY");
myAddress.state =
results.getString("STATE");
myAddress.zip = results.getInt("ZIP");
// get the credit card information
//from the customer table
myCreditCard = new CreditCard();
myCreditCard.number =
results.getString("CREDIT_NUMBER");
myCreditCard.expDate =
results.getString("CREDIT_DATE");
myCreditCard.type =
results.getString("CREDIT_TYPE");
myAddress.name =
results.getInt("CREDIT_NAME");
}
}
catch (SQLException sqle) {
throw new EJBException(sqle);
}
finally {
if (con!=null)
con.close();
}
}
}
El método ejbLoad(), usa la referencia ejbContext() hacia el EntityContext del bean para obtener la clave primaria del ejemplar. Esto asegura que usamos el índice correcto en la base de datos. Obviamente, el CustomerBean_BMP necesitará usar los métodos heredados setEntityContext() y unsetEntityContext().
El método ejbStore() es invocado sobre el bean, al final de la transación, justo antes de que el contenedor intente enviar todos los cambios a la base de datos.

import java.sql.Connection;

public class CustomerBean_BMP extends CustomerBean {

public void ejbLoad() {
... read data from database
}

public void ejbStore() {
Connection con;
try {
Integer primaryKey = (Integer)ejbContext.getPrimaryKey();
con = this.getConnection();
PreparedStatement sqlPrep = con.prepareStatement(
"UPDATE customer set " +
"last_name = ?, first_name = ?,
middle_name = ?, " +
"street = ?, city = ?, state = ?,
zip = ?, " +
"card_number = ?, card_date = ?, " +
"card_name = ?, card_name = ?, " +
"WHERE id = ?"
);
sqlPrep.setString(1,myName.last);
sqlPrep.setString(2,myName.first);
sqlPrep.setString(3,myName.middle);
sqlPrep.setString(4,myAddress.street);
sqlPrep.setString(5,myAddress.city);
sqlPrep.setString(6,myAddress.state);
sqlPrep.setString(7,myAddress.zip);
sqlPrep.setInt(8, myCreditCard.number);
sqlPrep.setString(9, myCreditCard.expDate);
sqlPrep.setString(10, myCreditCard.type);
sqlPrep.setString(11, myCreditCard.name);
sqlPrep.setInt(12,primaryKey.intValue());
sqlPrep.executeUpdate();
}
catch (SQLException sqle) {
throw new EJBException(sqle);
}
finally {
if (con!=null)
con.close();
}
}
}
En ambos métodos ejbLoad() y ejbStore() el bean sincroniza su propio estado con la base de datos usando JDBC. Si estudiamos el código cuidadosamente podríamos haber observado que el bean otiene sus conexiones a la base de datos desde una invocación misteriosa al método this.getConnection(). Un método todavía no implementado. El método getConnection() no es un método estándard EJB, sólo una ayuda privada implementada para ocultar los mecanismos de obtención de conexiones a bases de datos. Abajo tenemos la definicón del método getConnection().

import java.sql.Connection;

public class CustomerBean_BMP extends CustomerBean {

public void ejbLoad() {
... read data from database
}

public void ejbStore() {
... write data to database
}

private Connection getConnection() throws SQLException {

InitialContext jndiContext = new InitialContext();
DataSource source = (DataSource) jndiContext.lookup("java:comp/env/jdbc/myDatabase");
return source.getConnection();
}
}

Las conexiones a bases de datos se obtienen desde el contenedor usando un contexto JNDI por defecto llamado "JNDI Environment Naming Context" (ENC). El ENC proporciona acceso a almacenes de conexiones JDBC transacionales a través de la factoría de conexiones estándard, del tipo javax.sql.DataSource.
En BMP, los métodos ejbLoad() y ejbStore() los invoca el contenedor para sincronizar el ejemplar del bean con los datos en la base de datos. Para insertar y eliminar entidades en la base de datos, se implementan los métodos ejbCreate() y ejbRemove() con una lógica de acceso a bases de datos muy similar. Los métodos ejbCreate() se implementan para insertar un nuevo registro en la base de datos y los métodos ejbRemove() para eliminar los datos de una entidad de la base de datos. Estos métodos de una entidad son invocados por el contenedor en respuesta a invocaciones a sus correspondientes métodos en los interface home y remoto. Abajo podemos ver las implementaciones de estos métodos.

public void ejbCreate(Integer id) {
this.customerID = id.intValue();
Connection con;
try {
con = this.getConnection();
Statement sqlStmt =
con.createStatement("INSERT INTO customer id VALUES (" + customerID + ")");
sqlStmt.executeUpdate();
return id;
}
catch(SQLException sqle) {
throw new EJBException(sqle);
}
finally {
if (con!=null)
con.close();
}
}

public void ejbRemove() {
Integer primaryKey = (Integer)ejbContext.getPrimaryKey();
Connection con;
try {
con = this.getConnection();
Statement sqlStmt = con.createStatement("DELETE FROM customer WHERE id = "
+ primaryKey.intValue());
sqlStmt.executeUpdate();
}
catch(SQLException sqle) {
throw new EJBException(sqle);
}
finally {
if (con!=null)
con.close();
}
}

En BMP, la clase bean es responsable de implementar los métodos de búsqueda definidos en el interface home. Por cada método de búsqueda definido en el interface home debe haber el correspondiente método ejbFind() en la clase bean. Estos métodos localizan los registros del bean apropiado en la base de datos y devuelve sus claves primarias al contenedor. El contenedor convierte la clave primara en referencias a beans y los devuelve al cliente. Abajo tenemos un ejemplo de implementación del método ejbFindByPrimaryKey() en la clase CustomerBean_BMP, que corresponde al findByPrimaryKey() definido en el interface CustomerHome.

public Integer ejbFindByPrimaryKey(Integer primaryKey)
throws ObjectNotFoundException {
Connection con;
try {
con = this.getConnection();
Statement sqlStmt =
con.createStatement("SELECT * FROM Customer " + " WHERE customerID = " +
primaryKey.intValue());

ResultSet results = sqlStmt.executeQuery();
if (results.next())
return primaryKey;
else
throw ObjectNotFoundException();
}
catch (SQLException sqle) {
throw new EJBException(sqle);
}
finally {
if (con!=null)
con.close();
}
}

Los métodos de búsqueda de entidades simples como el de arriba devuelven una sóla clave primara y lanza una ObjectNotFoundException si no se localiza un registro correspondiente. Los métodos de búsqueda multi-entidad devuelven una colección (java.util.Enumeration o java.util.Collection) de claves primarias. El contenedor convierte la colección de claves primarias en una colección de referencias remotas, que son devueltas al cliente. Abajo tenemos un ejemplo de cómo el método ejbFindByZipCode() multi-entidad, que corresponde al método findByZipCode() definido en el interface CustomerHome, sería implementado en la clase CustomerBean_BMP.

public Enumeration ejbFindByZipCode(
int zipCode) {
Connection con;
try {
con = this.getConnection();
Statement sqlStmt =
con.createStatement("SELECT id FROM Customer " + " WHERE zip = " +zipCode);

ResultSet results = sqlStmt.executeQuery();
Vector keys = new Vector();
while(results.next()){
int id = results.getInt("id");
keys.addElement(new Integer(id));
}
return keys.elements();
}
catch (SQLException sqle) {
throw new EJBException(sqle);
}
finally {
if (con!=null)
con.close();
}
}
Si no se encuentran registros correspondientes, se devuelve una colección vacía al contenedor, que devuelve una colección vacía al cliente.
Con la implementación de todos estos métodos y unos pocos cambios menores en el descriptor de desarrollo del bean, el CustomerBean_BMP esta listo para ser desplegado como una entidad BMP.