12

I have something like this:

@Service
@Transactional
public class ServiceA {

    @Autowired
    SomeDAO1 dao1; 

    @Autowired
    ServiceB serviceB;

    public void methodServiceA() {

        serviceB.someMethodThatRunsInsertIntoDB(); 
        dao1.anotherMethodThatRunsInsertIntoDB(); 

    }

}

@Service
@Transactional
public class ServiceB {

     @Autowired
     Dao2 dao2;

     public void someMethodThatRunsInsertIntoDB() {
          dao2.insertXXX();
     }

}

My problem is: if serviceB.someMethodThatRunsInsertIntoDB() executes sucessfully but dao1.anotherMethodThatRunsInsertIntoDB() throw an exception, the changes made by serviceB are not rolled back. I need to rollback those changes in case an exception occur in dao1.anotherMethodThatRunsInsertIntoDB(). How can I do this?

// EDITED

Transaction configuration in spring-servlet.xml

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
</bean>

Is it relevant if one dao uses an EntityManager and the other dao uses JdbcTemplate to interact with DB?

//UPDATE -- EntityManager configuration

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
            <property name="generateDdl" value="true" />
        </bean>
    </property>

user2466251
  • 183
  • 1
  • 3
  • 11
  • Unless you are swallowing the exception in your dao methods this code should be working. Please add how you are calling the service method and how is transaction manager is setup. – madteapot Oct 21 '16 at 10:29
  • 1
    could you please provide your Spring xml configuration file? – Ye Win Oct 21 '16 at 10:39
  • I edited the post to add transaction xml configuration. – user2466251 Oct 21 '16 at 10:48
  • have a look at http://stackoverflow.com/questions/6777419/how-to-configure-spring-to-make-jpa-hibernate-and-jdbc-jdbctemplate-or-mybati or http://stackoverflow.com/questions/2673678/what-transaction-manager-should-i-use-for-jbdc-template-when-using-jpa and double check your spring config. – madteapot Oct 21 '16 at 11:39
  • Add your transaction manager configuration, show you use of the JdbcTemplate. DataSource configuration and entity manager configuration. – M. Deinum Oct 21 '16 at 13:37
  • Show us your imports, I've seen code where people would import the wrong (at)Transactional annotation and obviously nothing happened when it was time to rollback. – Jan Vladimir Mostert Oct 21 '16 at 15:28

4 Answers4

5

you need to pass rollbackFor parameter with type of your checked exception. It seems that spring rollbacks only on unchecked exceptions by default. More details: Spring transaction: rollback on Exception or Throwable

Community
  • 1
  • 1
hi_my_name_is
  • 4,894
  • 3
  • 34
  • 50
3

you need to use <tx:annotation-driven/> inside you spring configuration file to enable the annotation driven transaction management.

1

It's because your dao1.anotherMethodThatRunsInsertIntoDB() call does not support current transaction (ServiceA transaction).

You need to use below propagation level in your ServiceB class.

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class ServiceB {

REQUIRED: Spring REQUIRED behavior means that the same transaction will be used if there is an already opened transaction in the current bean method execution context. Create a new one if none exists. In short this means that if an inner(2nd Transaction) method causes a transaction to rollback, the outer(1st Transaction) method will fail to commit and will also rollback the transaction.

Propagation Means: Typically, all code executed within a transaction scope will run in that transaction. However, you have the option of specifying the behavior in the event that a transactional method is executed when a transaction context already exists. For example, code can continue running in the existing transaction (the common case); or the existing transaction can be suspended and a new transaction created. Spring offers all of the transaction propagation options familiar from EJB CMT. To read about the semantics of transaction propagation in Spring, see Transaction Propagation

Edited
Note: The only exceptions that set a transaction to rollback state by default are the unchecked exceptions (like RuntimeException). If you want checked exceptions to also set transactions to rollback you must configure them to do so, eg.

@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = YourCheckedException.class))
public class ServiceA {

Note: As I noticed, declarative transaction management is AOP based. This means that Spring wraps the transactional beans into a transactional proxy, which takes care of starting and committing transactions. This means that the method call must be intercepted by the proxy in order to be transactional. You need to make sure below config had in your Spring configuration file.

<tx:annotation-driven transaction-manager="transactionManager" />
Ye Win
  • 2,020
  • 14
  • 21
1

My first suggestion is to use @Transactional annotation on method level if it is really not needed on class level.

Second thing, try use javax.transaction.Transactional annotation instead of org.springframework.transaction.annotation.Transactional, Spring will automatically handle the propagation.

You also need to enable transaction management before using @Transactional, Using Spring Boot we can simply do that by marking Application class by @EnableTransactionManagement.

However, you can surely do this by XML configuration (<tx:annotation-driven />) as well if you want to. Read http://docs.spring.io/spring-data/jpa/docs/1.11.0.M1/reference/html/#transactions for more details

Naresh Joshi
  • 4,188
  • 35
  • 45