<persistence-unit name="name-unit" transaction-type="JTA">
During the development time, I had some difficulties to use persist to save data into database. Here are a few things I would like to share to pay attention when we work on this.
1. Setup persistence.xml. The following is what I used. The highlighted ones were new added when the code didn't work.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="name-unit" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/xxx/datasources/dsname</jta-data-source>
<class>xxx.model.Class</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="connection.driver_class" value="com.ibm.db2.jcc.DB2Driver" />
<property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
<property name="hibernate.connection.charSet" value="UTF-8" />
<property name="hibernate.max_fetch_depth" value="5" />
<property name="hibernate.connection.clientProgramName" value="supsearch" />
<property name="hibernate.cache.use_second_level_cache" value="false" />
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.hbm2ddl.import_files_sql_extractor" value="org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor" />
<property name="hibernate.validator.apply_to_ddl" value="false" />
<property name="hibernate.validator.autoregister_listeners" value="false" />
<property name="jboss.entity.manager.factory.jndi.name" value="java:/name-emf" />
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
<property name="hibernate.generate_statistics" value="true" />
</properties>
</persistence-unit>
</persistence>
2. Setup Spring JTA Transaction Manager and other JTA information
Spring will automatically discover the underlying JTA implementation.
We need to add JTA Transaction Manager into applicationContext.xml, in my case it is called web-persistence.xml.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Note: imported by SecurityConfig.java -->
<context:mbean-export/>
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/name-unit" expected-type="javax.persistence.EntityManagerFactory" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
<property name="persistenceUnits">
<map>
<entry key="name-unit" value="persistence/name-unit" />
</map>
</property>
<property name="persistenceContexts">
<map>
<entry key="name-unit" value="persistence/name-context"/>
</map>
</property>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven/>
<tx:jta-transaction-manager/>
</beans>
3. Injection via @PersistenceContext
The EntityManager itself is created by the container using the information in the persistence.xml, so to use it at runtime, we simply need to request it be injected into one of our components. We do this via @PersistenceContext.
@PersistenceContext should put into DAO impl. In my case it is called repository impl.
@Repository
public class XxxxClassRepositoryImpl implements
XxxxClassRepository, Serializable {
private static final long serialVersionUID = 1L;
@PersistenceContext
private EntityManager emgr;
4. Add @Transactional Annotation
In the DAO impl layer and service impl layer (if you have), we need to add @Transcational annotation in. This annotation can be added in the class level and method level.
@Repository
@Transactional
public class XxxxClassRepositoryImpl implements
XxxxClassRepository, Serializable {
private static final long serialVersionUID = 1L;
@PersistenceContext
private EntityManager emgr;
If you want to learn how Spring transactional really work, I found this blog is very helpful.
http://blog.jhades.org/how-does-spring-transactional-really-work/