user2482019
user2482019

Reputation: 51

Spring - JPA -m@Transactional not committing data in DB

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

Answers (4)

kboom
kboom

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

Balaji Natarajan
Balaji Natarajan

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

user2482019
user2482019

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

dursun
dursun

Reputation: 1846

you are to specifiy your transaction manager on your code

@Transactional("entityManager1")
public boolean saveMyGroups(

Upvotes: 0

Related Questions