Obtaining an EntityManager






Obtaining an EntityManager

Now that you have packaged and deployed your persistence units, you need to obtain access to an EntityManager so that you can persist, update, remove, and query your entity beans within your databases. In Java SE, entity managers are created using a javax.persistence.EntityManagerFactory . Although you can use the factory interface in Java EE, this platform provides some additional features that make it easier and less verbose to manage entity manager instances.

EntityManagerFactory

EntityManagers may be created or obtained from an EntityManagerFactory. In a Java SE application, you must use an EntityManagerFactory to create instances of an EntityManager. Using the factory isn't a requirement in Java EE.

package javax.persistence;

public interface EntityManagerFactory {
   EntityManager createEntityManager( );
   EntityManager createEntityManager(java.util.Map map);
   void close( );
   boolean isOpen( );
}

The createEntityManager( ) methods return EntityManager instances that manage a distinct extended persistence context. You can pass in a java.util.Map parameter to override or extend any provider-specific properties you did not declare in your persistence.xml file. When you are finished using the EntityManagerFactory, you should close( ) it (unless it is injected; ee'll discuss this later). The isOpen( ) method allows you to check to see if the EntityManagerFactory reference is still valid.

Getting an EntityManagerFactory in Java SE

In Java SE, the javax.persistence.Persistence class is responsible for bootstrapping an EntityManagerFactory:

public class Persistence {
   public static EntityManagerFactory createEntityManagerFactory(
           String unitName
   );
   public static EntityManagerFactory createEntityManagerFactory(
           String unitName,
           java.util.Map 
 properties
   );

The javax.persistence.Persistence class looks for persistence.xml deployment descriptors within your Java classpath. The unitName parameter you pass in will allow the Persistence implementation to locate an EntityManagerFactory that matches the given name. Additionally, you can override or add any vendor-specific properties defined in the <properties> element of the persistence.xml file by passing in a java.util.Map as a second parameter:

EntityManagerFactory factory = Persistence.createEntityManagerFactory("CRM");
...
factory.close( );

In Java SE, it is recommended that you close( ) the EntityManagerFactory. This frees up any resources that are being held by the factory.

Getting an EntityManagerFactory in Java EE

In Java EE, it is a bit easier to get an EntityManagerFactory. It can be injected directly into a field or setter method of your EJBs using the @javax.persistence.PersistenceUnit annotation:

package javax.persistence;

@Target({METHOD, FIELD, TYPE}) @Retention(RUNTIME)
public @interface PersistenceUnit {
   String name( ) default "";
   String unitName( ) default "";
}

The unitName( ) is the identity of the PersistenceUnit. When the PersistenceUnit is used, it not only injects the EntityManagerFactory, it also registers a reference to it within the JNDI ENC of the EJB. (The JNDI ENC is discussed more in chapter-11 and chapter-14.) The EJB container is responsible for noticing the @PersistenceUnit annotation and injecting the correct factory:

import javax.persistence.*;
import javax.ejb.*;

@Stateless
public MyBean implements MyBusinessInterface {

   @PersistenceUnit(unitName="CRM")
   private EntityManagerFactory factory;

   private EntityManagerFactory factory2;

   @PersistenceUnit(unitName="CUSTDB")
   public void setFactory2(EntityManagerFactory f) {
      this.factory2 = f;
   }

When an instance of the stateless session bean is created, the EJB container sets the factory field to the persistence unit identified by "CRM". It also calls the setFactory2( ) method with the "CUSTDB" persistence unit.

Unlike in Java SE, an injected EntityManagerFactory is automatically closed by the EJB container when the instance is discarded. In fact, if you call close( ) on an injected EntityManagerFactory, an IllegalStateException is thrown. The @PersistenceUnit annotation and its XML equivalent are covered in more detail in chapter-14.

Obtaining a Persistence Context

A persistence context can be created by calling the EntityManagerFactory.createEntityManager( ) method. The returned EntityManager instance represents an extended persistence context. If the EntityManagerFactory is JTA-enabled, then you have to explicitly enlist the EntityManager instance within a transaction by calling the EntityManager.joinTransaction( ) method. If you do not enlist the EntityManager within the JTA transaction, then changes you make to your entities are not synchronized with the database.

EntityManager.joinTransaction( ) is required to be invoked only when an EntityManager is created explicitly using an EntityManagerFactory. If you are using EJB container managed persistence contexts, then you do not need to perform this extra step.


Using the EntityManagerFactory API is a bit verbose and can be awkward when you are making nested EJB calls, for instance. Fortunately, EJB and the Java Persistence specification are nicely integrated. An EntityManager can be injected directly into an EJB using the @javax.persistence.PersistenceContext annotation (or equivalent XML discussed in Chapter 14):

package javax.persistence;

public enum PersistenceContextType
{
   TRANSACTION,
   EXTENDED 

}

public @interface PersistenceProperty {
   String name( );
   String value( );
}

@Target({METHOD, TYPE, FIELD}) @Retention(RUNTIME)
public @interface PersistenceContext {
   String name( ) default "";
   String unitName( ) default "";
   PersistenceContextType type( ) default TRANSACTION;
   PersistenceProperty[] properties( ) default {};
}

The @PersistenceContext annotation works in much the same way as @PersistenceUnit except that an entity manager instance is injected instead of an EntityManagerFactory:

@Stateless
public class MySessionBean implements MySessionRemote {
   @PersistenceContext(unitName="titan")
   private EntityManager entityManager;
...
}

The unitName( ) attribute identifies the persistence. By default, a transaction-scoped persistence context is injected when using this annotation. You can override this default with the type( ) attribute. When you access this transaction-scoped Entity-Manager, a persistence context becomes associated with the transaction until it finishes. This means that if you interact with any entity managers within the context of a transaction, no matter if they are different instances that are injected into different beans, the same persistence context will be used. The details of this annotation are discussed in chapter-14. Persistence context propagation is discussed in chapter-16.

You must never call close( ) on an injected entity manager. Cleanup is handled by the application server. If you close an entity manager, an IllegalStateException is thrown.

An EXTENDED entity manager can only be injected into a stateful session bean; stateless session and message-driven beans are pooled, and there would be no way to close the persistence context and release any managed entity instances. In order to obtain an extended context, a stateful session bean uses the @javax.persistence.PersistenceContext annotation with a type of EXTENDED:

@Stateful public class MyStatefulBean 
 implements MyStatefulRemote {
@PersistenceContext 
(unitName="titan",
type=PersistenceContextType.EXTENDED)
   private EntityManager manager;
...
}

When this MyStatefulBean is created, a persistence context is also created for the injected manager field. The persistence context has the same life span as the bean. When the stateful session bean is removed, the persistence context is closed. This means that any entity object instances remain attached and managed as long as the stateful session bean is active. chapter-11 has more details on this subject.

It is strongly suggested that you use the @PersistenceContext annotation or the XML equivalent when using Java Persistence with EJBs. These features were defined to make it easier for developers to interact with entity beans. Entity managers created using Entity-ManagerFactory are more error-prone because the application developer has to worry about more things. For instance, the developer could forget to close( ) an entity manager and leak resources. Take advantage of the ease-of-use facilities of your EJB container!




 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows