How can you slowly migrate existing Hibernate apps to JPA? How can you use Hibernate features and unique mapping capabilities with a JPA deployment? How can you take advantage of EJB3 injection and persistence context management with Hibernate? In this blog I want to show how Hibernate, JPA, and EJB 3.0 can co-exist and compliment one another. This information is fully documented between the Hibernate and JBoss EJB3 projects, but I thought I’d highlight them in this blog to make the community aware that they exist.
Mixing and matching JPA annotations within Hibernate
Using the standard JPA annotations helps out greatly in cutting down the amount of XML metadata you have to type. This annotation metadata is an exact replacement for much of the metadata in hbm.xml. Using them does not require you to use the JPA EntityManager interface. You may still use SessionFactory and Session objects to interact with your database. After downing the Hibernate Anotations project, setting things up is fairly easy:
SessionFactory sessionFactory = new AnnotationConfiguration().buildSessionFactory();
You use hibernate.cfg.xml to specify which exact classes you want mapped by this SessionFactory:
<hibernate-configuration> <session-factory> <mapping class="com.acme.Flight"/> <mapping class="org.jboss.Sky"/> <mapping resource="org.acme.orm.xml"/> </session-factory> </hibernate-configuration>
You can mix hbm.xml mapping files with new annotated classes. XML resources can also either be JPA-based XML or Hibernate based. This mixing and matching allows you to quickly prototype new mappings using JPA, but allows these mappings to co-exist with older Hibernate 3 applications.
There are a few more options for configuration. Check out the Hibernate Annotations documentation for more information.
Use Hibernate to configure JPA
If you want to use the JPA Entity Manager API to code a portable application, you may still want to use Hibernate metadata to map your beans. Although the JPA orm mapping is pretty rich, it is still a subset of Hibernate’s functionality. The Hibernate Annotations project provides additional Hibernate-specific annotations to elaborate a persistence mapping where JPA leaves off. If you prefer XML, you can use hbm.xml files to define the mappings for your entity beans. When loading a persistence archive, Hibernate Entity Manager will automatically scan the .jar file for any *hbm.xml files and add them to its mapping information.
Hibernate specific configuration is defined in the properties element of the persistence.xml file. You can configure any hibernate property within this XML blob
<persistence> <persistence-unit name="manager1" transaction-type="JTA"> <jta-data-source>java:/DefaultDS</jta-data-source> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> </persistence-unit> </persistence>
You may also define all your hibernate configuration in the usual Hibernate way: within a hibernate.xfg.xml file. You must tell the JPA implementation to use this configuration file through the hibernate.ejb.cfgfile property.
<persistence> <persistence-unit name="manager1" transaction-type="JTA"> <jta-data-source>java:/DefaultDS</jta-data-source> <properties> <property name="hibernate.ejb.cfgfile" value="/hibernate.cfg.xml"/> </properties> </persistence-unit> </persistence>
EJB 3.0 managed persistence sessions
EJB 3.0 has some nice integration with JPA. You can have your EJB session beans manage persistent sessions for you, freeing you from having to create, destroy, and clean up your persistence sessions. It can manage your persistent sessions in two ways:
Transaction-scoped persistence contexts
Transaction-scoped persistence contexts can be injected into your stateful, stateless, or message driven beans. These transaction-scoped contexts only live for the duration of the JTA transaction they are invoked within. When you first interact with an injected transaction-scoped EntityManager within a transaction, an underlying persistence context (in other words, a Hibernate session) is transparently created and associated with the transaction. This associated context is propagated automatically to an nested EJBs that invoke on entity managers of the same persistent unit type. This means that any EJB that invokes on an entity manager will be using the same underlying Hibernate Session.
@Statelesspublic class MyBean implements MyInterface { @PersistenceContext(unitName="custDb") EntityManager manager; ...
Extended persistence contexts
In Hibernate terminology, an extended persistence context is one particular Hibernate session. This session may live beyond the duration of a JTA transaction. In EJB 3.0, you can inject an extended persistence context into a stateful session bean. Unlike transaction-scoped entity managers, these persistence contexts are not created and destroyed in a transaction, but instead have their lifecylce tied to that of the SFSB session. This allows you to have conversations with your database that span multiple JTA transactions.
@Statefulpublic class ShoppingCartBean implements ShoppingCart { { @PersistenceContext(unitName="custDb", type=EXTENDED) EntityManager manager; ... }
Using EJB 3.0 injection annotations with Hibernate
The JBoss EJB 3.0 implementation allows you to use Hibernate Session and SessionFactory as types for targets of the @PersistenceContext and @PersistenceUnit annotations. The injected Session or SessionFactory will behave exactly as if you were instead using the JPA counterparts EntityManager or EntityManagerFactory:
@Statelesspublic class MyBean implements MyInterface { @PersistenceContext(unitName="custDb") org.hibernate.Session session; @PersistenceUnit(unitName="custDb") SessionFactory factory; ... }
Just like with the EJB 3.0/JPA integration, the Hibernate Session will be associated with the JTA transaction and propagated to nested EJB invocations within the same transaction. It is also ok if these nested calls use the EntityManager API instead. The same underlying Hibernate session will still be used for both.
Hiberate Sessions can also represent extended persistence contexts:
@Statefulpublic class ShoppingCartBean implements ShoppingCart { @PersistenceContext(type=EXTENDED) org.hibernate.Session session; ... }
Again, the EJB container will manage this Hibernate Session the same way it would manage an EntityManager instance.
Obtaining Hibernate objects programmatically
You can always get access to a Hibernate Session object from an EntityManager instance through the standard EntityManager.getDelegate() method. This is a JPA specification feature.
@PersistenceContext EntityManager manager; ... { org.hibernate.Session session = (Session)manager.getDelegate(); }
The specification, however, does not provide a way to get at the underlying implementation of a Query. Hibernate should provide most of its extended functionality through JPA query hints. For example, lets say you wanted to enable a query cache:
javax.persistence.Query query = manager.createQuery(...); query.setHint("org.hibernate.cacheable", true);
Conclusion
Hibernate and the JBoss EJB 3.0 project provide multiple ways in which you can mix and match Hibernate and JPA annotations and XML metadata. JBoss EJB 3.0 can manage Hibernate typed objects the same way it can manage JPA objects. Finally the specification provides programmatic ways to get at the underlying Hibernate connection. With the features you should have the flexibility to get at the HIbernate features you need while staying as portable as possible under the JPA specification. Or conversely, you can use well-defined JPA mapping annotations within your Hibernate deployments to make coding simpler and easier.
Disclaimer π This blog was meant to make you aware of certain integration features that exist between JPA, Hibernate, and JBoss EJB 3.0. You should not use it as a reference guide, but rather dive down deeper into each project’s docoumentation. Have fun.
Jul 23, 2007 @ 14:55:00
query.setHint(“org.hiberante.cacheable”, true);
Small correction
query.setHint(“org.hibernate.cacheable”, true); ?
Mar 15, 2008 @ 12:42:53
Thanks for such a great post Angry Bill! I’m new to Hibernate, JPA & EJB3 and with so many options it can be quite difficult to get an understanding of how to integrate the API’s and which strategy to use. Do you know of a resource that gives info on reasons to choose Hibernate over the standard JPA?
Mar 15, 2008 @ 16:43:20
Ray, why Hibernate of JPA. Hibernate is a superset of JPA. it has things like a Criteria API and more complex mapping options than JPA as well as funkier caching strategies like query caching.
Mar 16, 2008 @ 11:28:43
Thanks for that info Bill, I’m liking Hibernate over JPA already :o)
Jun 15, 2009 @ 08:03:53
Bill, thanks for the post, it’s quite helpful! I am wonder if Jboss has a way to support multiple persist unit WITHOUT Seam? such as has multiple data source in oracle-ds.xml, and map to persistence.xml as multiple , I guess need , and use EntityManager em = (EntityManager) context.lookup(MyEntityManger);
I tried that, but only got the first manager in the list, do I have to use Seam and component.xml?
Can you post the implementation if there is a way?
Thanks
Jun 28, 2009 @ 12:17:35
Someone pointed out that the following method is not portable across different application servers using Hibernate.
What’s your consideration? Which approach would you suggest if we want to obtain such object from the entity manager.
BTW, great article.
org.hibernate.Session session = (Session)manager.getDelegate();
Jul 13, 2009 @ 08:01:26
Thanks.
I try to make a basic web application based on JAVA , JSP , Servlet , EJB3.0 , hibernate … using Eclipse Ganymede AS5.0 , and so on …and I found this is quite complicated to get the information I need .
So many thanks to make thinks clearer.
Mar 23, 2010 @ 18:19:06
Bill,
Nice post, thanks. It was exactly what I was looking for: a way to mix and match JPA and pure Hibernate. JPA is fine, and I’m using it exclusively in an application right now. However, I’ve recently seen the power of the Hibernate Criteria API as well as the Hibernate JPA extensions, and it’s inspired me to attempt to mix the two together, especially in my service layer where I do all of my CRUD. Hibernate is an old player in the ORM world, and it’s got tricks up its sleeves that JPA can’t match.
May 03, 2010 @ 21:05:48
Bill Very good post thanks,
One question for you.
If I use a JTA transaction either Entityanager or Hibernate session behave in same way.
But if I annotate the method using:
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
(I don’t want to use transactions)the entityManager.find method and session.get method with same parameters behave different due to, the object returned by find method throws Lazy exceptions in collections (in the same method in session bean) and the object obtained via get method behaves without problem.
Any explanation for this strange behaviour?
Regards,
Carlos
Sep 20, 2010 @ 11:29:31
Hi Carlos,
I am interested in the same matter. The section 13.6.5 of ejb-3_0-fr-spec-ejbcore.pdf says, that the behaviour is not specified by JEE spec and left to the the implementation. So I guess, the EntityManager is implemented to tread each call as a separate transaction. While Hibernate session may behave more “common Hibernate way”.
Oct 25, 2010 @ 21:45:52
Mmm good point I will read about it, but it does make sense. Thanks!
Oct 28, 2010 @ 20:02:07
can i mix jpa and seesion calls within a single transaction?
Dec 06, 2011 @ 17:03:17
hi… greetings…
its good.. about .. EJB and Hibernate….
but.. you dint give… any… Exaple… on that.. for better.. understanding….
Jun 25, 2012 @ 05:49:47
Hi good article..
I Have small doubt about Persistence Context..
If am using more than one persistence unit in Persistence.xml
like
org.hibernate.ejb.HibernatePersistence
java:jboss/datasources/MySqlDS
org.hibernate.ejb.HibernatePersistence
java:jboss/datasources/MyDS
Now I want to access persistence unit name dynamically
@PersistenceContext(unitName = “abcd”) *******************
In this place I hardcoded persistnce unit name but sometimes I want to use “xyz” also which is available in persistence.xml
What should one can do to dynamically pass the unitName into the
—- @PersistenceContext(unitName=””) ——-
I have a problem in this.. Please do provide a solution for this its urgent for my project.
Jun 25, 2012 @ 05:51:23
Hi good article..
I Have small doubt about Persistence Context..
If am using more than one persistence unit in Persistence.xml
like
org.hibernate.ejb.HibernatePersistence
java:jboss/datasources/MySqlDS
org.hibernate.ejb.HibernatePersistence
java:jboss/datasources/MyDS
Now I want to access persistence unit name dynamically
@PersistenceContext(unitName = \βabcd\β) *******************
In this place I hardcoded persistnce unit name but sometimes I want to use \βxyz\β also which is available in persistence.xml
What should one can do to dynamically pass the unitName into the
β- @PersistenceContext(unitName=\β\β) ββ-
I have a problem in this.. Please do provide a solution for this its urgent for my project.