Warp :: Hibernate integration

Warp it! Store it! Get going in seconds! new!

Wideplay's integration for Hibernate 3

If you dont know what Hibernate is, odds are you have been living in a cave (irony unintended =). Warp-persist supports Hibernate integration with the Persistence support module. Simply drop the jar in and follow the instructions below to get going with various typical usage profiles.

Enabling Persistence Support

To enable persistence support, configure the module when creating your injector:

Injector injector = Guice.createInjector(..., PersistenceService.usingHibernate()
			 .buildModule());
 

You must bind in your Hibernate configuration in one of your own modules, for instance:

bind(Configuration.class).toInstance(new AnnotationConfiguration().addResource(...));
Note: Do not call buildSessionFactory()!!!!

Finally, you must decide when the persistence service is to be started by invoking start() on the PersistenceService. I typically use a simple initializer class that I can bind and invoke at a time of my choosing:

public class MyInitializer { 
	@Inject MyInitializer(PersistenceService service) {
		service.start();
	} 
} 

A really simple approach would be to bind MyInitializer as an eager singleton so the PersistenceService is started up when Guice starts up; but I recommend you think about how it fits into your particular deployment environment before doing so.

Session-per-transaction strategy

This is a popular strategy, where a Hibernate session is created and destroyed around each database transaction. To use it, set the following properties for Hibernate:

hibernate.transaction.factory_class=org.hibernate.transaction.JDBCTransactionFactory
hibernate.current_session_context_class=thread
 

And change the PersistenceModule's configuration accordingly:

Injector injector = Guice.createInjector(..., PersistenceService
			.usingHibernate()
			.across(UnitOfWork.TRANSACTION)
			.buildModule());
 

Note: this is the default UnitOfWork strategy even if unspecified (as in the earlier example).

Using the Session inside Transactions

Once you have the injector created, you can freely inject and use a session in your transactional services:

import com.wideplay.warp.persist.Transactional;
import org.hibernate.Session;
... 
 
public class MyService {
	@Inject Provider<Session> session; 
 
	@Transactional 
	public void createNewPerson() {
		session.get().saveOrUpdate(new Person(...)); 
	} 
 

Note that since we are using a session-per-transaction strategy, you cannot hold a reference to the session instance across transactions (must obtain it from the provider each time). See the session-per-http-request strategy if this doesn't work for you.

Transaction semantics

See the transactions guide for detailed information on managing and using transactions.

Usage in Web Environments (session-per-http-request)

So far, we've only used a session-per-transaction strategy. In web environments this is atypical, and generally session-per-http-request is preferred (such as with the popular open-session-in-view paradigm). To enable this strategy, you first need to add a filter to web.xml:

	<filter>
		<filter-name>sessionPerRequestFilter</filter-name>
		<filter-class>com.wideplay.warp.hibernate.SessionPerRequestFilter</filter-name>
	</filter>
	<filter-mapping>
		<filter-name>sessionPerRequestFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
 

It doesn't really matter where this filter appears (however, if you are using warp-widgets, it must appear before WidgetFilter). Then in your injector configuration:

Injector injector = Guice.createInjector(..., PersistenceService
			.usingHibernate()
			.across(UnitOfWork.REQUEST)
			.buildModule());
 

Finally your hibernate configuration should be modified with the following property set (do not set hibernate.transaction.factory_class):

hibernate.current_session_context_class=managed
 

Note that with this configuration you can run multiple transactions within the same request (and the same session). This fits well with open-session-in-view.