Reputation: 51
I have seen many questions but all of their solution still not clear. here is my set up my Spring Context file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
..
...
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
...
...
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="entityManagerFactory1"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
autowire="byName">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.my.dom.domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle10gDialect
</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="persistenceUnitName" value="PersistenceUnit1"></property>
</bean>
<bean id="EntityManagerFactory2"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
autowire="byName">
<property name="dataSource" ref="myDataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.my.dom.domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.H2Dialect
</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
..
...
<bean id="entityManager1" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory1" />
</bean>
<tx:annotation-driven transaction-manager="entityManager1" />
<bean id="EntityManager2" factory-bean="EntityManagerFactory2" factory-method="createEntityManager" autowire="byName" scope="prototype"/>
<tx:annotation-driven transaction-manager="EntityManager2" />
<context:component-scan base-package="com.my.dom" />
<jpa:repositories base-package="com.my.dom.repository"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
</beans>
All data source and other connection beans are in place and working fine.
My DAO code is as follows package com.my.dom.dao;
@Component
public class MyDAOImpl implements MyDAO {
@PersistenceContext(unitName="PersistenceUnit1")
EntityManager entityManager; // this is IAR EntityManager.
@Override
@Transactional
public boolean saveMyGroups(
List<MyGroups> theGroups) {
logger.info("Entering method - saveFuturetheGroups ");
//entityManager.getTransaction().begin();
for(MyGroups pg : theGroups){
MyGroups attachedENtity = entityManager.merge(pg);
entityManager.persist(pg);
}
//entityManager.getTransaction().commit();
entityManager.flush();
logger.info("Exiting method - saveFuturetheGroups ");
//List<MyGroups> savedEntities = futureProcGrpRepository.save(theGroups);
return true;
}
}
I have all the cglib and aopalliance1.0.jars in classpath as suggested in Spring+JPA @Transactional not committing
Still my code is not committing the changes to DB. ANy help pointers will be really helpful.
The code shows select and insert sql statements and no exceptions throws but code doesnt commit. Is there any issues in @Transactional annotation?
Can defining multiple entitymanagers be any issues here?
Ok what I have found is that if I use @Transactional(propagation=Propagation.REQUIRES_NEW)
on top of my method it commits the changes !! But as per my under standing the default value for Propagation is 'REQUIRED' which any way will start a new transction and should commit at end? Any pointers I am now really confused!!
Thanks HK
Just a note , I am running this from A Junit test case , is it possible that it is explicitely rolling back the changes? I see something like following in logs
INFO : org.springframework.test.context.transaction.TransactionalTestExecutionListener - Rolled back transaction after test execution for test context [[TestContext@a5503a testClass = ProcessingGroupsTestCase, testInstance = null(com.wellmanage.dos.processingGroups.ProcessingGroupsTestCase), testMethod = testSave@ProcessingGroupsTestCase, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@1363f5a testClass = ProcessingGroupsTestCase, locations = '{classpath:applicationContext.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader']]]
Thanks HK
Upvotes: 1
Views: 8859
Reputation: 2339
In my case, you just don't want to put @Transactional annotation on the test itself (or the class it's in) and it will solve the issue without having to include:
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=false)
which could make unit-testing difficult and is "true" by default for a good reason.
So just make your controller-layer methods @Transactional and do not do this on the tests - they will see modified data then.
Upvotes: 0
Reputation: 202
By default, defaultRollback is set you true for junit tests, which means, even if you don't specify @TransactionConfiguration, data updated through junit tests will be rolled back.
Setting defaultRollback=false explicitly will solve this issue.
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=false)
Upvotes: 3
Reputation: 51
Ok Guys!! its all my stupidity.. and I beleive I should admit it. All the time I was running the whole DAO and service through my TestCase and I just overlooked the following in my TestCase.
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=true)
@Transactional
The defaultRollback=true was culprit.
What lessons I have learnt. Never ever overlook any code and always try to find issues from beginning of code.
So to make a Spring work with JPA - Have proper context entries (as in my example) - Use @Transactional as in my DAO.
and you should be all set.
Thanks HK
Upvotes: 4
Reputation: 1846
you are to specifiy your transaction manager on your code
@Transactional("entityManager1")
public boolean saveMyGroups(
Upvotes: 0