Entity Beans

Unlike session beans, entity beans are long-lived components. They represent data in an object-oriented way, while the data typically resides in a relational database. The API provides methods to create, look up, update, and delete entity beans without necessitating client beans or client applications to handle SQL statements. Entity beans will survive after normal (or abnormal) termination of their clients.

An entity bean instance basically represents a row in a database table. It is therefore totally stateful because it contains member attributes that correspond to a table’s columns. The EJB framework provides techniques to map database tables to entity beans.

Two options are available to provide persistence to entity beans: The container can either provide the mechanism for the database mapping (container-managed persistence) or delegate it to the bean developer (bean-managed persistence). For example, the iPlanet Application Server provides such a container.

Container-managed persistence

When using container-managed persistence, a programmer doesn’t need to provide the code to insert, update, delete, and select data from a database. She actually doesn’t need to use JDBC at all. The container generates the mapping code at deployment time or uses the features of an object-relational bridge for this purpose. Although this option leaves little room for developers to control all interactions with databases, it is a quite powerful and fast technique to implement distributed business components.

As shown in Listing 10-4, the code for an entity bean using container-managed persistence is fairly simple. It basically contains only member attributes for the bean.

Listing 10-4: Entity Bean with Container-Managed Persistence

start example
import javax.ejb.EntityBean; import javax.ejb.CreateException; import javax.ejb.RemoveException; public class AccountBean implements EntityBean {   public String accountId; // also the primary Key   public double balance;   public void ejbActivate() {   }   public void ejbPassivate() {   }   public void ejbLoad() {   }   public void ejbStore() {   }   public void ejbRemove() throws RemoveException   {   }   public String ejbCreate(String accountId, double initialBalance) throws  CreateException   {     this.accountId = accountId;     this.balance   = initialBalance;     return null;   }   public void ejbPostCreate(String accountId, double initialBalance)    {   }   public double deposit(double amount)   {     balance += amount;     return balance;   }   public double withdraw(double amount)   {     balance -= amount;     return balance;   }   public double balance()   {     return balance;   } }
end example

Note 

Application server tools are used to generate database-mapping code for this type of entity bean. The developer, or more often the deployer of the application, can specify which bean attributes map to which database table columns in so-called deployment descriptors. There is a one-to-one relationship between attributes and columns in such descriptors. It is unnecessary to recompile the whole set of beans when mapping information is updated: The deployment tools of the application server take care of this mapping.

Bean-managed persistence

In the second case, bean-managed persistence, a developer must provide the necessary methods to make the data represented by the entity bean stay in sync with data residing in a database table. The methods that have to be implemented are as follows:

  • public void ejbLoad(): Synchronizes the bean’s attributes with the corresponding data residing in the database.

  • public void ejbStore(): Synchronizes the data residing in the database with the bean’s attributes.

  • public String ejbCreate(params...): Creates a new instance of a bean and inserts the corresponding data in a database table.

  • public void ejbRemove(): Deletes persistent data for this bean in the database.

  • public String ejbFindByPrimaryKey(String pk): Loads this bean’s attributes with the corresponding data from a table, using the primary key to locate the row.

  • public Enumeration ejbFindByXXX(params...): Returns an enumeration of all primary keys of rows matching certain criteria (similar to a SQL WHERE clause).

Using bean-managed persistence is much more complex than using container-managed persistence. The following example illustrates the AccountBean again, but this time using bean-managed persistence. The important life cycle methods that make the synchronization with the database are implemented in Listing 10-5. Note that a programmer never actually calls these methods. They are implicitly called by the container.

Listing 10-5: Entity Bean with Bean-Managed Persistence

start example
import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.ejb.CreateException; import javax.ejb.RemoveException; public class AccountBean implements EntityBean {   private EntityContext ctx;   private String accountId; // also the primary Key   private double balance;   public void setEntityContext(EntityContext ctx) {     this.ctx = ctx;   }   public void unsetEntityContext() {     this.ctx = null;   }   public void ejbActivate() {   }   public void ejbPassivate() {   }   public void ejbLoad() {     Connection conn = null;     PreparedStatement ps = null;     accountId = (String) ctx.getPrimaryKey();     try {       conn = getConnection();       ps  = conn.prepareStatement("SELECT balance FROM accounts WHERE id = ?");       ps.setString(1, accountId);       ps.executeQuery();       ResultSet rs = ps.getResultSet();       if (rs.next()) {         balance = rs.getDouble(1);       } else {         throw new NoSuchEntityException (accountId + " not found");        }     } catch (SQLException e) {       throw new EJBException(e);     } finally {       try {         if (ps != null) ps.close();         if (conn != null) conn.close();       } catch (Exception e) {           throw new EJBException(e);       }     }   }   public void ejbStore() {     Connection conn = null;     PreparedStatement ps = null;     try {       conn = getConnection();       ps = conn.prepareStatement("UPDATE accounts SET balance = ? WHERE id = ?");       ps.setDouble(1, balance);       ps.setString(2, accountId);       if (!(ps.executeUpdate() > 0)) {         throw new NoSuchEntityException (accountId + " not found");       }     } catch(SQLException e) {       throw new EJBException (e);     } finally {       try {         if (ps != null) ps.close();         if (conn != null) conn.close();       } catch (Exception e) {           throw new EJBException(e);       }     }   }   public void ejbRemove() throws RemoveException   {     Connection conn = null;     PreparedStatement ps = null;     try {       conn = getConnection();       accountId = (String) ctx.getPrimaryKey();       ps = conn.prepareStatement("DELETE FROM accounts WHERE id = ?");       ps.setString(1, accountId);       if (!(ps.executeUpdate() > 0)) {         throw new NoSuchEntityException (accountId + " not found");       }     } catch (SQLException e) {       throw new EJBException (e);     } finally {       try {         if (ps != null) ps.close();         if (conn != null) conn.close();       } catch (Exception e) {           throw new EJBException(e);       }     }   }   public String ejbCreate(String accountId, double initialBalance) throws CreateException   {     this.accountId = accountId;     this.balance   = initialBalance;     Connection conn = null;     PreparedStatement ps = null;     try {       conn = getConnection();       ps = conn.prepareStatement("INSERT INTO accounts (id, balance)  VALUES (?, ?)");       ps.setString(1, accountId);       ps.setDouble(2, balance);       if (ps.executeUpdate() != 1) {         throw new CreateException ("not created");       }       return accountId;     } catch (SQLException e) {       try {         ejbFindByPrimaryKey(accountId);       } catch(ObjectNotFoundException onfe) {         throw new CreateException (e);       }       throw new DuplicateKeyException(accountId);     } finally {       try {         if (ps != null) ps.close();         if (conn != null) conn.close();       } catch (Exception e) {           throw new EJBException(e);       }     }     return null;   }   public void ejbPostCreate(String accountId, double initialBalance)    {   }   public String ejbFindByPrimaryKey(String pk) throws ObjectNotFoundException   {     Connection conn = null;     PreparedStatement ps = null;     try {       conn = getConnection();       ps  = conn.prepareStatement("SELECT balance FROM accounts WHERE id = ?");       ps.setString(1, pk);       ps.executeQuery();       ResultSet rs = ps.getResultSet();       if (rs.next()) {         balance = rs.getDouble(1);       } else {         throw new ObjectNotFoundException (pk + " not found");        }     } catch (SQLException e) {       throw new EJBException (e);     } finally {       try {         if (ps != null) ps.close();         if (conn != null) conn.close();       } catch (Exception e) {           throw new EJBException(e);       }     }     return pk;   }   public double deposit(double amount)   {     balance += amount;     return balance;   }   public double withdraw(double amount)   {     balance -= amount;     return balance;   }   public double balance()   {     return balance;   } }
end example

Container-managed persistence versus bean-managed persistence

Using container-managed persistence has several advantages over using bean-managed persistence. However, the second technique allows more complex queries involving joins, for example, or queries involving stored procedures to be executed. Table 10-1 summarizes the advantages and disadvantages of both approaches.

Table 10-1: CONTAINER-MANAGED PERSISTENCE (CMP) VERSUS BEAN-MANAGED PERSISTENCE (BMP)

Advantage

CMP

BMP

Portability

Very portable with respect to the application server and database

Table names and SQL queries are hard-coded in the beans, which makes them less portable

Performance

Application servers may provide an enhanced object-relational bridge and caching technology

Developers are responsible for achieving the performance level that they require

JDBC code must be provided by the developer

No

Yes

Finer control on database mapping

No

Yes

Self-contained components (components that don’t need external code to integrate with databases)

Yes

Yes

Deployment tool facilities for database mapping at deployment time

Available

Not available

Maintenance of code

Easier because the code is database independent

More complex if several databases must be used or table names and queries have to be changed



JDBC 3. 0. JAVA Database Connectivity
JDBC 3: Java Database Connectivity
ISBN: 0764548751
EAN: 2147483647
Year: 2002
Pages: 148

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net