Throughout the life of an entity, its data
will be changed by client applications. In the
ShipBean
, we provide accessor methods to change
the name
, capacity
, and
tonnage
of the Ship EJB after it has been created.
Invoking any of these accessor methods changes the state of the
ShipBean
instance, and these changes must be
reflected in the database.
In container-managed persistence, synchronization between the entity
bean and the database takes place automatically; the container
handles it for you. With bean-managed persistence, you are
responsible for synchronization: the entity bean must read from and
write to the database directly. The container works closely with the
BMP entities by advising them when to synchronize their state through
the use of two callback methods: ejbStore()
and
ejbLoad()
.
The ejbStore()
method is called when the container
decides that it is a good time to write the entity bean’s data
to the database. The container makes these decisions based on all the
activities it is managing, including transactions, concurrency, and
resource management. Vendor implementations may differ slightly as to
when the ejbStore()
method is called, but this is
not the bean developer’s concern. In most cases, the
ejbStore()
method will be called after one or more
business methods have been invoked or at the end of a transaction.
Here is the ejbStore()
method for the
ShipBean
:
public void ejbStore() { Connection con = null; PreparedStatement ps = null; try { con = this.getConnection(); ps = con.prepareStatement( "update Ship set name = ?, capacity = ?, " + "tonnage = ? where id = ?"); ps.setString(1,name); ps.setInt(2,capacity); ps.setDouble(3,tonnage); ps.setInt(4,id.intValue()); if (ps.executeUpdate() != 1) { throw new EJBException("ejbStore"); } } catch (SQLException se) { throw new EJBException (se); } finally { try { if (ps != null) ps.close(); if (con!= null) con.close(); } catch(SQLException se) { se.printStackTrace(); } } }
Except for the fact that we are doing an update instead of an insert,
this method is similar to the ejbCreate()
method
we examined earlier. We use a JDBC
PreparedStatement
to execute the SQL
UPDATE
command, and we use the entity bean’s
persistence fields as parameters to the request. This method
synchronizes the database with the state of the bean.
EJB also provides an ejbLoad()
method that
synchronizes the state of the entity with the database. This method
is usually called at the start of a new transaction or
business-method invocation. The idea is to make sure that the bean
always represents the most current data in the database, which could
be changed by other beans or other non-EJB applications.
Here is the ejbLoad()
method for a bean-managed
ShipBean
class:
public void ejbLoad() { Integer primaryKey = (Integer)context.getPrimaryKey(); Connection con = null; PreparedStatement ps = null; ResultSet result = null; try { con = this.getConnection(); ps = con.prepareStatement( "select name, capacity, tonnage from Ship where id = ?"); ps.setInt(1, primaryKey.intValue()); result = ps.executeQuery(); if (result.next()){ id = primaryKey; name = result.getString("name"); capacity = result.getInt("capacity"); tonnage = result.getDouble("tonnage"); } else { throw new EJBException(); } } catch (SQLException se) { throw new EJBException(se); } finally { try { if (result != null) result.close(); if (ps != null) ps.close(); if (con!= null) con.close(); } catch(SQLException se) { se.printStackTrace(); } } }
To execute the ejbLoad()
method, we need a primary
key. To get the primary key, we query the bean’s
EntityContext
. Note that we don’t get the
primary key directly from the ShipBean
’s
id
field, because we cannot guarantee that this
field is always valid—the ejbLoad()
method
might be populating the bean instance’s state for the first
time, in which case the fields would all be set to their default
values. This situation would occur following bean activation. We can
guarantee that the EntityContext
for the
ShipBean
is valid because the EJB specification
requires that the bean instance’s
EntityContext
reference be valid before the
ejbLoad()
method can be invoked.
At this point you may want to jump to Chapter 11
and read Section 11.4 to
get a better understanding of the
EntityContext
’s purpose and usefulness in
entity beans.