To enable transactions in a JPA component, you need to provide the JPA
component with a reference to a transaction manager, of
JpaTransactionManager
type. The Java Persistence API is a
generic wrapper API for object-relational persistence and it can be layered over
a variety of different object-relational mapping technologies.
Example 2.4 shows how to customize the configuration of a JPA component (creating a component with the bean ID, jpa), so that the JPA component supports Spring transactions. When used with transactions, the JPA component requires a reference to an entity manager factory and a reference to a transaction manager.
Example 2.4. JPA Transaction Manager Configuration
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="transactionManager" ref="jpaTxManager"/> </bean> <bean id="jpaTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <property name="persistenceUnitName" value="camel"/> </bean> </beans>
In Example 2.4, the
jpaTxManager
bean is a local JPA transaction manager instance,
of JpaTransactionManager
type. The JPA transaction manager requires
a reference to an entity manager factory bean (in this example, the
entityManagerFactory
bean).
If you deploy your application into an OSGi container, however, you might want
to consider using a JtaTransactionManager
instead. See Table 2.2.
The entity manager factory bean encapsulates the JPA runtime functionality.
For example, the Spring LocalEntityManagerFactoryBean
class is just a wrapper around the standard
javax.persistence.EntityManagerFactory
class. The entity
manager factory is used to create a javax.persistence.EntityManager
instance, where the entity manager is associated with a unique
persistence context. A persistence context represents
a consistent set of entity objects that are instantiated from the underlying
database (analogous to a Hibernate session).
The LocalEntityManagerFactoryBean
class is a relatively simple
JPA wrapper class that is suitable for simple demonstrations and testing
purposes. This class reads its required configuration information from the
persistence.xml
file, which is found at the standard location,
META-INF/persistence.xml
, on the class path (see Sample persistence.xml file). The
persistenceUnitName
property references a section of the
persistence.xml
file.
As well as instantiating a LocalEntityManagerFactoryBean
bean,
there are other ways of obtaining a JPA entity manager factory, as summarized in
Table 2.7.
Table 2.7. Obtaining JPA Entity Manager Factory
Entity Manager Factory | Description |
---|---|
Obtain from JNDI | If your application is deployed in a J2EE container, the recommended approach is to let the container take care of instantiating the entity manager factory. You can then obtain a reference to the entity manager factory using JNDI. See Obtaining an EntityManagerFactory from JNDI in the Spring documentation. |
LocalEntityManagerFactoryBean | For simple standalone applications and for testing, the
simplest option is to create a bean of this type. The JPA
runtime is configured using the standard
META-INF/persistence.xml file. |
LocalContainerEntityManagerFactoryBean | Use this class, if you need to configure special bootstrap options for the JPA runtime. In spite of the name, this class is not restricted to containers; you can also use it in standalone mode. See LocalContainerEntityManagerFactoryBean in the Spring documentation. |
The JPA is a thin abstraction layer that allows you to write code that is independent of a particular object-relational mapping product—for example, it enables you to layer your application over products such as OpenJPA, Hibernate, or TopLink. To match the application code to a specific JPA implementation, JPA defines a bootstrap contract, which is a procedure to locate and configure JPA implementations, as follows:
To make a JPA implementation available to your application, put the JAR file containing the relevant JPA provider class (of
javax.persistence.spi.PersistenceProvider
type) on your class path. In fact, it is possible to add multiple JPA providers to your class path: you can optionally specify which JPA provider to use in thepersistence.xml
file.The JPA persistence layer is configured by the standard
persistence.xml
file, which is normally located inMETA-INF/persistence.xml
on the class path.
Example 2.5 shows a sample
persistence.xml
file for configuring an OpenJPA JPA
provider layered over a Derby database.
Example 2.5. Sample persistence.xml File
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="camel" transaction-type="RESOURCE_LOCAL"> <!-- The default provider can be OpenJPA, or some other product. This element is optional if OpenJPA is the only JPA provider in the current classloading environment, but can be specified in cases where there are multiple JPA implementations available. --> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl </provider> <class>org.apache.camel.examples.MultiSteps</class>
<class>org.apache.camel.examples.SendEmail</class> <properties>
<property name="openjpa.ConnectionURL" value="jdbc:derby:target/derby;create=true"/> <property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.EmbeddedDriver"/> <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/> <property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO, SQL=TRACE"/> </properties> </persistence-unit> </persistence>
The To make a JPA provider available to an application, simply add the provider's JAR file to the class path and the JPA layer will auto-detect the JPA provider. | |
Use the | |
Use the |
The following code example shows how the
org.apache.camel.examples.SendEmail
class referenced
in Example 2.5 should be annotated to turn
it into a persistent entity bean (so that it is persistible by JPA):
// Java package org.apache.camel.examples; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; /** * Represents a task which is added to the database, then removed from the database when it is consumed * * @version $Revision$ */ @Entity public class SendEmail { private Long id; private String address; public SendEmail() { } public SendEmail(String address) { setAddress(address); } @Override public String toString() { return "SendEmail[id: " + getId() + " address: " + getAddress() + "]"; } @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
The preceding class has the following JPA annotations:
@javax.persistence.Entity
Specifies that the following class is persistible by the JPA.
@javax.persistence.Id
The following bean property must be used as the primary key (for locating objects of this type in the database).
@javax.persistence.GeneratedValue
Specifies that the primary key values should be automatically generated by the JPA runtime (you can optionally set attributes on this annotation to configure the ID generation algorithm as well).
For the complete list of JPA annotations, see the API for the javax.persistence
package.