SeamFramework.orgCommunity Documentation

Chapter 29. Seam Persistence Reference

29.1. Introduction
29.2. Getting Started
29.3. Seam-managed persistence contexts
29.3.1. Using a Seam-managed persistence context with JPA
29.3.2. Seam-managed persistence contexts and atomic conversations
29.3.3. Using EL in EJB-QL/HQL
29.3.4. Setting up the EntityManager

Seam provides extensive support for the two most popular persistence architectures for Java: Hibernate3, and the Java Persistence API introduced with EJB 3.0. Seam's unique state-management architecture allows the most sophisticated ORM integration of any web application framework.

Note

Previously the Seam Persistence module provided transactional-related features also, however as transactions are not an exclusive feature of the persistence domain, these features have been moved into a separate module called Seam Transactions.

Seam grew out of the frustration of the Hibernate team with the statelessness typical of the previous generation of Java application architectures. The state management architecture of Seam was originally designed to solve problems relating to persistence — in particular problems associated withoptimistic transaction processing. Scalable online applications always use optimistic transactions. An atomic (database/JTA) level transaction should not span a user interaction unless the application is designed to support only a very small number of concurrent clients. But almost all interesting work involves first displaying data to a user, and then, slightly later, updating the same data. So Hibernate was designed to support the idea of a persistence context which spanned an optimistic transaction.

Unfortunately, the so-called "stateless" architectures that preceded Seam and EJB 3.0 had no construct for representing an optimistic transaction. So, instead, these architectures provided persistence contexts scoped to the atomic transaction. Of course, this resulted in many problems for users, and is the cause of the number one user complaint about Hibernate: the dreaded LazyInitializationException. What we need is a construct for representing an optimistic transaction in the application tier.

EJB 3.0 recognizes this problem, and introduces the idea of a stateful component (a stateful session bean) with an extended persistence context scoped to the lifetime of the component. This is a partial solution to the problem (and is a useful construct in and of itself) however there are two problems:

Seam solves the first problem by providing conversations, and stateful session bean components scoped to the conversation. (Most conversations actually represent optimistic transactions in the data layer.) This is sufficient for many simple applications (such as the Seam booking demo) where persistence context propagation is not needed. For more complex applications, with many loosely-interacting components in each conversation, propagation of the persistence context across components becomes an important issue. So Seam extends the persistence context management model of EJB 3.0, to provide conversation-scoped extended persistence contexts.

To get started with Seam Persistence you need to add seam-persistence.jar and solder-impl.jar to your deployment. The relevant Maven configuration is as follows:


<dependency>
  <groupId>org.jboss.seam.persistence</groupId>
  <artifactId>seam-persistence-api</artifactId>
  <version>${seam.persistence.version}</version>
</dependency>

<dependency>
  <groupId>org.jboss.seam.persistence</groupId>
  <artifactId>seam-persistence</artifactId>
  <version>${seam.persistence.version}</version>
</dependency>

<dependency>
  <groupId>org.jboss.solder</groupId>
  <artifactId>solder-impl</artifactId>
  <version>${solder.version}</version>
</dependency>

You will also need to have a JPA provider on the classpath. If you are using java EE this is taken care of for you. If not, we recommend hibernate.


<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>3.5.1-Final</version>
</dependency>

If you're using Seam outside of a Java EE environment, you can't rely upon the container to manage the persistence context lifecycle for you. Even if you are in an EE environment, you might have a complex application with many loosely coupled components that collaborate together in the scope of a single conversation, and in this case you might find that propagation of the persistence context between component is tricky and error-prone.

In either case, you'll need to use a managed persistence context (for JPA) or a managed session (for Hibernate) in your components. A Seam-managed persistence context is just a built-in Seam component that manages an instance of EntityManager or Session in the conversation (or any other) context. You can inject it with@Inject.

@ExtensionManaged
@Produces
@PersistenceUnit
@ConversationScoped
EntityManagerFactory producerField;

This is just an ordinary resource producer field as defined by the CDI specification, however the presence of the @ExtensionManaged annotation tells seam to create a seam managed persistence context from thisEntityManagerFactory. This managed persistence context can be injected normally, and has the same scope and qualifiers that are specified on the resource producer field.

This will work even in a SE environment where @PersistenceUnit injection is not normally supported. This is because the seam persistence extensions will bootstrap the EntityManagerFactory for you.

Now we can have our EntityManager injected using:

@Inject EntityManager entityManager;