Simplify enterprise Java development with EJB 3.0, Part 2

POJO persistence made easy

1 2 Page 2
Page 2 of 2

A .par file is a jar file of the entity bean classes together with a simple configuration file META-INF/persistence.xml. The persistence.xml file defines the name of this persistence context. It tells the EJB 3.0 container which backend database (DataSource) to use for this set of entity beans. The persistence.xml file also contains implementation-specific configuration properties. For instance, JBoss EJB 3.0 is implemented on top of Hibernate 3.0. So you can pass any Hibernate configuration options in the persistence.xml file. Here is an example persistence.xml file with JBoss- and Hibernate-specific configuration properties on the SQL dialect and the second-level cache:

 <entity-manager>
  <name>cal</name>
  <jta-data-source>java:/DefaultDS</jta-data-source>
  <properties>
    <property name="hibernate.dialect"  
            value="org.hibernate.dialect.MySQLDialect" />
    <property name="hibernate.cache.provider_class"
            value="org.jboss.ejb3.entity.TreeCacheProviderHook"/>
    <property name="hibernate.treecache.mbean.object_name"
            value="jboss.cache:service=EJB3EntityTreeCache"/>
  </properties>
</entity-manager>

The EntityManager

Once you have the entity beans deployed, you must access and manipulate them via the EJB 3.0 EntityManager API. The EJB 3.0 container provides one EntityManager object for each deployed persistence context (i.e., the .par file). From an EJB 3.0 session bean POJO (see Part 1), you can inject the EntityManager object via the @PersistenceContext annotation and pass in the name of the context:

 

@Stateless public class ManagerBean implements Manager {

@PersistenceContext (unitName="cal") protected EntityManager em; // Use "em" // ... ... }

Basic operations

To create a new data object and save it to the database, you can simply use the Java new keyword to create the POJO and pass it to the EntityManager.persist() method:

 Person p = new Person ();
p.setName ("A new baby");
p.setDateOfBirth (new Date ());
em.persist (p);

To retrieve objects from the database, you can use the EJB 3.0 Query Language to search the database. The following example shows how to get all rows in the Person database table to return as a collection of Person Java objects:

 // Get all persons
Collection <Person> persons = (Collection <Person>) 
    em.createQuery("from Person p").getResultList();

Managed POJOs

The objects saved and retrieved by the EntityManager are managed in the persistence context. That means if the objects change later, the changes are automatically detected and persisted to the database. In the following example, we update a property of a managed POJO. The change is automatically detected by the EJB 3.0 container and sent to the database.

 

Person p = em.find(Person.class, personId); p.setName ("Another Name");

// p is automatically updated to the database // at the end of the current transaction. // No additional API calls.

Since EJB 3.0 entity beans are just POJOs, they can be serialized and passed over the network. If an object is not created by the container (e.g., it is passed in from a network connection or is a return value from a remote procedure call), the persistence context does not manage it. You can merge a nonmanaged POJO into the persistence context by calling the EntityManager.merge() method. Below is an example of merging a deserialized POJO into the current persistence context:

 

InputStream in; // Initialize the input stream. Person p = Util.deserialize (in);

// ... ... em.merge (p);

// p is a managed object now. Any change to p // is automatically detected and persisted. p.setName ("Another Name");

Database synchronization

When the EntityManager object is used in a session bean, it is tied with the server's transaction context. The EntityManager commits and synchronizes its contents to the database when the server's transaction commits. In a session bean, the server transaction commits at the end of the call stack by default. Of course, you can also specify the detailed transactional properties of each business method via annotations. The example below shows how to declare a new transaction for a session bean method:

 @TransactionAttribute(TransactionAttributeType.REQUIRESNEW)
public void update () {
  // Update Person objects in this method
  // and all updates are committed and flushed
  // to the database at the end of this method.
}  

Flushing database operations in a batch
To only flush changes to the database when a transaction commits, the container can group database operations in a batch and reduce the expensive database roundtrips.

If you need to flush the updates to the database before the transaction commits, you can call the EntityManager.flush() method explicitly. Or you may tag a method with the @FlushMode(FlushModeType.NEVER) annotation, and the transaction manager will not flush the updates to the database at the end of this method (i.e., the end of the transaction). In this case, you can manually flush all database updates to achieve the most control.

In conclusion

EJB 3.0 provides a simple and effective framework for mapping Java POJOs to relational tables in SQL databases. It uses sensible default mapping strategies based on the structure and naming of the Java class. Yet you can also override any defaults and handle complex object relationships using a simple set of annotations.

The EJB 3.0 EntityManager provides simple APIs to persist, find, and search objects from the database. Each EntityManager object is associated with a set of mapped POJOs and has its own database settings. It is also automatically tied to the application server's transaction manager.

Dr. Michael Yuan works for JBoss. He specializes in end-to-end enterprise solutions. He is the author of three books, Nokia Smartphone Hacks, Enterprise J2ME, and Nokia Series: Developing Scalable Series 40 Applications. Yuan received a Ph.D. degree from the University of Texas at Austin.

Learn more about this topic

1 2 Page 2
Page 2 of 2