Entity manager
The entity manager is similar to the Hibernate Session class; applications use it to create/read/update/delete data (and related operations). Applications can use application-managed or container-managed entity managers. Keep in mind that the entity manager is not expected to be thread safe (don't inject it into a servlet class variable which is visible to multiple threads).
Application-managed entity manager
Application-managed entity managers provide direct access to the underlying persistence provider (org.hibernate.ejb.HibernatePersistence). The scope of the application-managed entity manager is from when the application creates it and lasts until the app closes it. Use the @PersistenceUnit annotation to inject a persistence unit into a javax.persistence.EntityManagerFactory. The EntityManagerFactory can return an application-managed entity manager.
Container-managed entity manager
Container-managed entity managers auto-magically manage the underlying persistence provider for the application. Container-managed entity managers may use transaction-scoped persistence contexts or extended persistence contexts. The container-managed entity manager will create instances of the underlying persistence provider as needed. Every time that a new underlying persistence provider (org.hibernate.ejb.HibernatePersistence) instance is created, a new persistence context is also created (as an implementation detail of the underlying persistence provider).
Persistence Context
The JPA persistence context contains the entities managed by the persistence provider. The persistence context acts like a first level (transactional) cache for interacting with the datasource. Loaded entities are placed into the persistence context before being returned to the application. Entities changes are also placed into the persistence context (to be saved in the database when the transaction commits).
Transaction-scoped persistence context
The transaction-scoped persistence context coordinates with the (active) JTA transaction. When the transaction commits, the persistence context is flushed to the datasource (entity objects are detached but may still be referenced by application code). All entity changes that are expected to be saved to the datasource, must be made during a transaction. Entities read outside of a transaction will be detached immediately (since there is no transaction to coordinate with). Example transaction-scoped persistence context is below.
@Stateful // will use container managed transactions
public class CustomerManager {
@PersistenceContext(unitName = "customerPU") // default type is PersistenceContextType.TRANSACTION
EntityManager em;
public customer createCustomer(String name, String address) {
Customer customer = new Customer(name, address);
em.persist(customer); // persist new Customer when JTA transaction completes (when method ends).
// internally:
// 1. Look for existing "customerPU" persistence context in active JTA transaction and use if found.
// 2. Else create new "customerPU" persistence context (e.g. instance of org.hibernate.ejb.HibernatePersistence)
// and put in current active JTA transaction.
return customer; // return Customer entity (will be detached from the persistence context when caller gets control)
} // Transaction.commit will be called, Customer entity will be persisted to the database and "customerPU" persistence context closed
Container-managed Extended Persistence context
The Container-managed extended persistence context can span multiple transactions and allows data modifications to be queued up (like a shopping cart), without an active JTA transaction (to be applied during the next JTA TX). The Container-managed extended persistence context can only be injected into a stateful session bean.
@PersistenceContext(type = PersistenceContextType.EXTENDED, unitName = "inventoryPU")
EntityManager em;
Entities
JPA 2.0 makes it easy to use your (pojo) plain old Java class to represent a database table row.
@PersistenceContext EntityManager em;
Integer bomPk = getIndexKeyValue();
BillOfMaterials bom = em.find(BillOfMaterials.class, bomPk); // read existing table row into BillOfMaterials class
BillOfMaterials createdBom = new BillOfMaterials("..."); // create new entity
em.persist(createdBom); // createdBom is now managed and will be saved to database when the current JTA transaction completes
The entity lifecycle is managed by the underlying persistence provider.
-
New (transient): an entity is new if it has just been instantiated using the new operator, and it is not associated with a persistence context. It has no persistent representation in the database and no identifier value has been assigned.
-
Managed (persistent): a managed entity instance is an instance with a persistent identity that is currently associated with a persistence context.
-
Detached: the entity instance is an instance with a persistent identity that is no longer associated with a persistence context, usually because the persistence context was closed or the instance was evicted from the context.
-
Removed: a removed entity instance is an instance with a persistent identity, associated with a persistence context, but scheduled for removal from the database.
Deployment
The persistence.xml contains the persistence unit configuration (e.g. datasource name) and as described in the JPA 2.0 spec (section 8.2), the jar file or directory whose META-INF directory contains the persistence.xml file is termed the root of the persistence unit. In Java EE environments, the root of a persistence unit must be one of the following:
"
-
an EJB-JAR file
-
the WEB-INF/classes directory of a WAR file
-
a jar file in the WEB-INF/lib directory of a WAR file
-
a jar file in the EAR library directory
-
an application client jar file
The persistence.xml can specify either a JTA datasource or a non-JTA datasource. The JTA datasource is expected to be used within the EE environment (even when reading data without an active transaction). If a datasource is not specified, the default-datasource will instead be used (must be configured).
NOTE: Java Persistence 1.0 supported use of a jar file in the root of the EAR as the root of a persistence unit. This use is no longer supported. Portable applications should use the EAR library directory for this case instead.
"
Question: Can you have a EAR/META-INF/persistence.xml?
Answer: No, the above may deploy but it could include other archives also in the EAR, so you may have deployment issues for other reasons. Better to put the persistence.xml in an EAR/lib/somePuJar.jar.
Troubleshooting
The “org.jboss.as.jpa” logging can be enabled to get the following information:
-
INFO - when persistence.xml has been parsed, starting of persistence unit service (per deployed persistence.xml), stopping of persistence unit service
-
DEBUG - informs about entity managers being injected, creating/reusing transaction scoped entity manager for active transaction
-
TRACE - shows how long each entity manager operation took in milliseconds, application searches for a persistence unit, parsing of persistence.xml
To enable TRACE, open the as/standalone/configuration/standalone.xml (or as/domain/configuration/domain.xml) file. Search for <subsystem xmlns="urn:jboss:domain:logging:1.0"> and add the org.jboss.as.jpa category :
<subsystem xmlns="urn:jboss:domain:logging:1.0">
<console-handler name="CONSOLE">
<level name="TRACE" />
...
</console-handler>
<periodic-rotating-file-handler name="FILE">
<level name="TRACE" />
.
.
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN" />
</logger>
<logger category="org.jboss.as.jpa">
<level name="TRACE" />
</logger>
<logger category="org.apache.tomcat.util.modeler">
<level name="WARN" />
</logger>
...
Using the Hibernate 4 JPA persistence provider
Hibernate 4 is packaged with the AS and is the default persistence provider.
Packaging the Hibernate 3.5 or greater 3.x JPA persistence provider with your application
AS 7.0.1 allows the packaging of Hibernate 3.5 (or greater) persistence provider jars with the application. The JPA deployer will detect the presence of a persistence provider in the application and jboss.as.jpa.providerModule needs to be set to hibernate3-bundled.
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="plannerdatasource_pu">
<description>Hibernate 3 Persistence Unit.</description>
<jta-data-source>java:jboss/datasources/PlannerDS</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="false" />
<property name="jboss.as.jpa.providerModule" value="hibernate3-bundled" />
</properties>
</persistence-unit>
</persistence>
The AS7 testsuite contains a test that packages jars from the Hibernate 3.6.5.Final jars (hibernate3-core.jar, hibernate3-commons-annotations.jar, hibernate3-entitymanager.jar, dom4j.jar, slf4j.jar, slf4j-api.jar, commons-collections.jar, antlr.jar) in the ear lib.
Sharing the Hibernate 3.5 or greater JPA persistence provider between multiple applications
Applications can share the same Hibernate3 (for Hibernate 3.5 or greater) persistence provider by manually creating an org.hibernate:3 module (in the AS/modules folder). Steps to create the Hibernate3 module:
-
In a command shell, go to the AS installation and change into the modules/org folder.
cd AS/modules/org or cd AS\modules\org\hibernate
-
Create folder for slot 3 to hold Hibernate 3
mkdir 3
cd 3
-
Copy the Hibernate3 jars into this new AS/modules/org/hibernate/3 folder
(hibernate3-core.jar, hibernate3-commons-annotations.jar, hibernate3-entitymanager.jar, dom4j.jar, slf4j.jar, slf4j-api.jar, commons-collections.jar, antlr.jar, slf4j-api.jar, commons-collections.jar, antlr.jar and any other jar needed for Hibernate 3).
-
Create the AS/modules/org/hibernate/3/module.xml file with contents:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="org.hibernate" slot="3">
<resources>
<resource-root path="hibernate3-core.jar"/>
<resource-root path="hibernate3-commons-annotations.jar"/>
<resource-root path="hibernate3-entitymanager.jar"/>
<resource-root path="javassist-3.12.0.GA.jar"/>
<resource-root path="antlr-2.7.6.jar"/>
<resource-root path="commons-collections-3.1.jar"/>
<resource-root path="dom4j-1.6.1.jar"/>
<!-- Insert other Hibernate 3 jars to be used here -->
</resources>
<dependencies>
<module name="org.jboss.as.jpa.hibernate" slot="3"/>
<module name="asm.asm"/>
<module name="javax.api"/>
<module name="javax.persistence.api"/>
<module name="javax.transaction.api"/>
<module name="javax.validation.api"/>
<module name="org.apache.ant"/>
<module name="org.infinispan"/>
<module name="org.javassist"/>
<module name="org.slf4j"/>
</dependencies>
</module>
In your persistence.xml, you will refer to the Hibernate 3 persistence provider as follows:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="crm_pu">
<description>CRM Persistence Unit.</description>
<jta-data-source>java:jboss/datasources/CRMDS</jta-data-source>
<properties>
<property name="jboss.as.jpa.providerModule" value="org.hibernate:3" />
</properties>
</persistence-unit>
</persistence>
Packaging a different version of Hibernate 4.x jars with the application
The static Hibernate 4.x (modules/org/hibernate/main) jars take precedence over the Hibernate 4.x jars that are packaged with your application. You can package Hibernate 3 jars because there is no conflict with the Hibernate 4.x jars in the modules/org.hibernate/main folder. Instead of packaging Hibernate 4.x jars with the application, update the shared Hibernate 4.x jars in the modules/org.hibernate/main folder as mentioned below.
Updating the Hibernate 4.x jars to a different Hibernate 4.x version
To update from Hibernate 4.0.1.Final which is bundled with AS to Hibernate 4.1.0.Final, download the 4.1.0.Final package from sourceforge, which contains all the jars required for update. Extract the archive and copy hibernate-core-4.1.0.Final.jar and hibernate-entitymanager-4.1.0.Final.jar to modules/org/hibernate/main directory and update the following entries
<resources>
...
<resource-root path="hibernate-core-4.0.1.Final.jar"/>
<resource-root path="hibernate-entitymanager-4.0.1.Final.jar"/>
...
</resources>
in the module.xml
<resources> ...
<resource-root path="hibernate-core-4.1.0.Final.jar"/>
<resource-root path="hibernate-entitymanager-4.1.0.Final.jar"/>
...
</resources>
it is also required to update the hibernate-infinispan module by copying the hibernate-infinispan-4.1.0.Final.jar to modules/org/hibernate/infinispan/main and the hibernate-envers-4.1.0.Final.jar to modules/org/hibernate/envers/main and updating the module.xml for both modules accordingly.
Working with other persistence providers
This is a work in progress. A project to build integration for persistence providers like EclipseLink, is here. It looks like help from the EclipseLink community, would be helpful (in adding AS7 support to EclipseLink or suggesting how existing builds of EclipseLink could be used). EclipseLink contains integration classes for each of the different runtime environments (like earlier versions of JBoss AS). We also need to fix the AS7 persistence unit temp class path.
Integration code for other persistence providers can also be added to the jpa-modules project. Note that the project is in its very early stages and you need to build AS7 locally on the same machine (so that the snapshot versions of the AS7 JPA SPI jars will be available). Also note that the AS7 JPA SPI is likely to evolve a bit as we add additional integration modules. It will stabilize more when we have integrated persistence providers from three different sources (We already have Hibernate integrated, so that is one of three needed).
If your interested in helping integrate AS7 with other persistence providers, please find Scott Marlow on IRC (irc://irc.freenode.org/jboss-as7) or send email to [].
Native Hibernate use
Applications that use the Hibernate API directly, are referred to here as native Hibernate applications. Native Hibernate applications, can choose to use the Hibernate jars included with JBoss AS or they can package their own copy of the Hibernate jars. Applications that utilize JPA will automatically have the JBoss AS Hibernate injected onto the application deployment classpath. Meaning that JPA applications, should expect to use the Hibernate jars included in JBoss AS.
Example MANIFEST.MF entry to add Hibernate dependency:
Manifest-Version: 1.0
...
Dependencies: org.hibernate
Injection of Hibernate Session and SessionFactoryInjection of Hibernate Session and SessionFactory
You can inject a org.hibernate.Session and org.hibernate.SessionFactory directly, just as you can do with EntityManagers and EntityManagerFactorys.
import org.hibernate.Session;
import org.hibernate.SessionFactory;
@Stateful public class MyStatefulBean ... {
@PersistenceContext(unitName="crm") Session session1;
@PersistenceContext(unitName="crm2", type=EXTENDED) Session extendedpc;
@PersistenceUnit(unitName="crm") SessionFactory factory;
}
Persistence unit properties
The following properties are supported in the persistence unit definition (in the persistence.xml file):
Property
|
Purpose
|
jboss.as.jpa.providerModule
|
is the name of the persistence provider module (default is org.hibernate). Should be hibernate3-bundled if Hibernate 3 jars are in the application archive (adapterModule and adapterClass will automatically be set for hibernate3-bundled).
|
jboss.as.jpa.adapterModule
|
is the name of the integration classes that help the AS to work with the persistence provider. Current valid values are org.jboss.as.jpa.hibernate:4 (Hibernate 4 integration classes) and org.jboss.as.jpa.hibernate:3 (Hibernate 3 integration classes). Other integration adapter modules are expected to be added.
|
jboss.as.jpa.adapterClass
|
is the class name of the integration adapter. Current valid values are org.jboss.as.jpa.hibernate3.HibernatePersistenceProviderAdaptor and org.jboss.as.jpa.hibernate4.HibernatePersistenceProviderAdaptor.
|