Spring's EntityManager not persisting
- by Fernando Camargo
Well, my project was using EJB and JPA (with Hibernate), but I had to switch to Spring.
Everything was working well before that. The EJB used to inject the EntityManager, controled the transaction, etc.
Ok, when I switched to Spring, I had a lot of problems because I'm new on Spring. But after everything is running, I have the problem: the data is never saved on database. I configured my Spring to control the transactions, I have spring beans used in JSF, that has spring services that do the hard work. This services have a EntityManager injected and use @Transactional REQUIRED. This services pass the EntityManager to a DAO that call entityManager.persist(bean).
The selects appears to work well, the JTA transaction appears to work well to (I saw in log), but the entity is not saved!
Here is the log:
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter: doFilterInternal() (linha 136): Opening JPA EntityManager in OpenEntityManagerInViewFilter
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.beans.factory.support.DefaultListableBeanFactory: doGetBean() (linha 245): Returning cached instance of singleton bean 'transactionManager'
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: getTransaction() (linha 365): Creating new transaction with name [br.org.cni.pronatec.controller.service.MontanteServiceImpl.adicionarValor]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: doBegin() (linha 493): Opened new Session [org.hibernate.impl.SessionImpl@2b2fe2f0] for Hibernate transaction
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: doBegin() (linha 504): Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@2b2fe2f0]
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: doBegin() (linha 569): Exposing Hibernate transaction as JDBC transaction [com.sun.gjc.spi.jdbc40.ConnectionHolder40@3bcd4840]
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler: doJoinTransaction() (linha 383): Joined JTA transaction
INFO: Hibernate:
select
hibernate_sequence.nextval
from
dual
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: processCommit() (linha 752): Initiating transaction commit
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: doCommit() (linha 652): Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@2b2fe2f0]
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.HibernateTransactionManager: doCleanupAfterCompletion() (linha 734): Closing Hibernate Session [org.hibernate.impl.SessionImpl@2b2fe2f0] after transaction
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.hibernate3.SessionFactoryUtils: closeSession() (linha 800): Closing Hibernate Session
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter: doFilterInternal() (linha 154): Closing JPA EntityManager in OpenEntityManagerInViewFilter
INFO: [Pronatec] - 04/04/2012 11:30:20 - [DEBUG] org.springframework.orm.jpa.EntityManagerFactoryUtils: closeEntityManager() (linha 343): Closing JPA EntityManager
In the log, I see it commiting the transaction, but I don't see the insert query (the Hibernate is printing any query). I also see that the Hibernate lookup to get the next value of the sequence ID. But after that, it never really inserts.
Here is the spring context configuration:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="PronatecPU" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
<property name="transactionManagerName" value="java:/TransactionManager" />
<property name="userTransactionName" value="UserTransaction" />
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<tx:annotation-driven transaction-manager="transactionManager" />
Here is my persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="PronatecPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/pronatec</jta-data-source>
<class>br.org.cni.pronatec.model.bean.AgendamentoBuscaSistec</class>
<class>br.org.cni.pronatec.model.bean.AgendamentoExportacaoZeus</class>
<class>br.org.cni.pronatec.model.bean.AgendamentoImportacaoZeus</class>
<class>br.org.cni.pronatec.model.bean.Aluno</class>
<class>br.org.cni.pronatec.model.bean.Curso</class>
<class>br.org.cni.pronatec.model.bean.DepartamentoRegional</class>
<class>br.org.cni.pronatec.model.bean.Dof</class>
<class>br.org.cni.pronatec.model.bean.Escola</class>
<class>br.org.cni.pronatec.model.bean.Inconsistencia</class>
<class>br.org.cni.pronatec.model.bean.Matricula</class>
<class>br.org.cni.pronatec.model.bean.Montante</class>
<class>br.org.cni.pronatec.model.bean.ParametrosVingentes</class>
<class>br.org.cni.pronatec.model.bean.TipoCurso</class>
<class>br.org.cni.pronatec.model.bean.Turma</class>
<class>br.org.cni.pronatec.model.bean.UnidadeFederativa</class>
<class>br.org.cni.pronatec.model.bean.ValorAssistenciaEstudantil</class>
<class>br.org.cni.pronatec.model.bean.ValorHora</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="current_session_context_class" value="thread"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
Here is my service that is injected in the managed bean:
@Service
@Scope("prototype")
@Transactional(propagation= Propagation.REQUIRED)
public class MontanteServiceImpl {
// more code
@PersistenceContext(unitName="PronatecPU", type= PersistenceContextType.EXTENDED)
private EntityManager entityManager;
// more code
// The method that is called by another public method that do something before
private void salvarMontante(Montante montante) {
montante.setDataTransacao(new Date());
MontanteDao montanteDao = new MontanteDao(entityManager);
montanteDao.salvar(montante);
}
// more code
}
My MontanteDao inherits from a base DAO, like this:
public class MontanteDao extends BaseDao<Montante> {
public MontanteDao(EntityManager entityManager) {
super(entityManager);
}
}
And the method that is called in BaseDao is this:
public void salvar(T bean) {
entityManager.persist(bean);
}
Like you can see, it just pick the injected entityManager and call the persist() method. The transaction is being controlled by the Spring, like is printed in the log, but the insert query is never printed in log and it is never saved.
I'm sorry about my bad english.
Thanks in advance for who helps.