Hibernate and JPA
Fabric3 provides first-class SCA/Hibernate integration by allowing EntityManager and Hibernate Session instances to be injected into components. These injected instances are managed by the Fabric3 runtime, alleviating the need for applications to manually manage persistence contexts through mechanisms such as ThreadLocal variables. In addition, Fabric3 provides consistent transactional behavior for applications using Hibernate, whether they are deployed to a testing environment such as Ant and Maven or a production environment such as Tomcat or the Fabric3 Server.
Data Access Features
Data access features supported by Fabric3 include:
- Injection of entity manager factories using
@PersistenceUnit
annotation - Injection of entity managers using{{ @PersistenceContext}} annotation
- Injection of Hibernate Session objects using the
@PersistenceContext
. Hibernate Session injection provides components access to Hibernate APIs. - Injection of XA and non-XA DataSource instances
- JDBC connection pooling
- Support for extended and transaction scope entity managers
- Integration with SCA transaction policies
- Transaction optimization across persistence units
Injection
EntityManager and EntityManagerFactory instances are injected into component implementations using the @PersistenceContext
and @PersistenceUnit
from the javax.persistence package respectively. These annotations are made available to all contributions at runtime. The following example demonstrates injecting an EntityManager:
public class EmployeeDAOImpl implement EmployeeDAO { @PersistenceContext(unitName="employee") protected EntityManager em; public void save(Employee employee) { m.persist(employee); } }
In the above examples, the persistence unit "employee" is defined in a JPA persistence.xml file. This file can needs to be located in the /META-INF
directory in the contribution containing the components for JAR-based contributions.
The following shows the persistence.xml file:
<persistence xmlns="http:{color}//java.sun.com/xml/ns/persistence"...> <persistence-unit name="employee" transaction-type="JTA"> <jta-data-source>EmployeeDS</jta-data-source> <class>org.fabric3.jpa.model.Employee</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> </properties> </persistence-unit> </persistence>
Similarly, Hibernate Session instances can be injected by changing the injected type to org.hibernate.Session
:
public class EmployeeDAOImpl implement EmployeeDAO { @PersistenceContext(unitName="employee") { protected Session session; public void save(Employee employee) { session.save(employee); } }
Remember that a component that uses Annotations of the javax.persistence API also needs to have access to the annotations at runtime. To enable this, add the the following import to the sca-contribution.xml file:
<import.java package="javax.persistence.*" version="2.0.0"/>
}
Otherwise, persistence contexts will not be injected.
Transactions
Fabric3 transparently integrates JPA and Hibernate with SCA declarative transactions. When a transaction is active, EntityManager and Session operations will be executed in the context of that transaction. The following performs transactional database work:
@ManagedTransaction public class EmployeeDAOImpl implement EmployeeDAO { @PersistenceContext(unitName="employee") protected EntityManager em; public void save(Employee employee) { m.persist(employee); } }
In the above example, a new transaction will be started if one does not exist. All operations performed against the injected EntityManager instance will take place in the newly-created or existing transaction context. If the transaction completes successfully, the EntityManager will be flushed and changes written to the database. Otherwise, a rollback will be issued, discarding any changes.
Using JDBC Directly
Applications may require direct access to a DataSource in order to use JDBC. DataSource instances can be injected using the org.fabric3.api.annotation.Resource annotation where the name value corresponds to a configured DataSource name:
public class EmployeeDAOImpl implement EmployeeDAO { @Resource(name="EmployeeDataSource") protected DataSource dataSource; // ... }
Managing Persistence Contexts and Sessions
Hibernate Session statistics are available via the Management Resource Framework and JMX.
Persistence Context Overrides
It is often necessary to provide different persistence context properties for specific deployment environments such as testing and production. For example, a developer test environment may use an embedded database while production deployments require MySQL, Oracle or DB2. Persistence context properties can be specified in a separate composite or as part of the runtime systemConfig.xml as follows:
<f3:persistence> <f3:persistenceUnit name="employee"> <f3:properties> <f3:property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> <f3:property name="hibernate.hbm2ddl.auto" value="create-drop"/> </f3:properties> </f3:persistenceUnit> </f3:persistence>
The above example adds two properties to the employee persistence context that is defined in a contribution. Overrides can also be combined with environment-specific composite activation to allow different configuration contained in a single contribution to be enabled based on the environment a runtime is booted in.
For more details on deployment configuration, see Packaging For Different Environments.
Logging
To set the Hibernate log level, add the <jpa> element to the runtime systemConfig.xml, with the value SEVERE, WARNING, INFO, DEBUG, or TRACE:
<config> <jpa logging="DEBUG"/> <!-- ... -->
Enabling Hibernate and JPA
JPA and Hibernate support is provided via a a set of optional extensions which must be installed in the runtime. These extensions contain the Fabric3 Hibernate extensions as well as a JTA transaction manager (Atomikos) and an XA-compliant DataSource pooling implementation. As a convenience, the required extensions are packaged together in a Fabric3 profile.
To install JPA support in the Fabric3 Server or Tomcat, download the JPA profile from the Fabric3 web site and copy the appropriate jars into the /extensions directory. After you restart the server, JPA support will be activated.
JPA support can be added to the Ant and Maven runtimes by specifying the profile-jpa profile in the build script configuration.