Is spring transaction is only working in entering service method?

386 views Asked by At

I have read many stackoverflow's pages about spring transaction. My spring transaction config is

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

My service is like this.

@Service
public class TestServiceImpl implements TestService {
     @Override
     public void testRollback() {
          testRollbackSecondLevel();
     }

     @Transactional
     @Override
     public void testRollbackSecondLevel() {
         // any update sql in here
         carCostService.testUpdate();

         throw new RuntimeException();
    }
}

then I write a test class to test, In my test code, when I use

// this test is not roll back, and the Transactional even not created
@Test
public void testTransactional() {
    // use this function, the Transactional don't work
    interCityService.testRollback();
}

// this test is roll back successfully
@Test
public void testTransactionalSecondLevel() {
    // but if I use the second level function instead of the first function,
    // the Transactional works fine, and the data can roll back
    interCityService.testRollbackSecondLevel();
}

And I debug the code, when I use the first test, transactional even not be created. The second one can create the transactional successfully.

I use the sql to judge the transaction is exist.

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX\G

If the sql return empty set, so no transaction be has been created.

So what's the problem? thanks in advance.

I use the spring version 4.1.2.RELEASE.

2

There are 2 answers

1
hi_my_name_is On BEST ANSWER

spring @Transactional works using proxies, that means that calling method with this annotation from same class does not have any influence == @Transactional is going to be ignored. There are maaaaany topics about it, please take a look at deeper explanation for example here: Spring @Transaction method call by the method within the same class, does not work?

0
paul On

If you want all your method service transactional add the transactional annotation as class and not method level

@Transactional
@Service
public class TestServiceImpl implements TestService {

   @Override
   public void testRollback() {
        testRollbackSecondLevel();
   }


 @Override
 public void testRollbackSecondLevel() {
     // any update sql in here
     carCostService.testUpdate();

     throw new RuntimeException();
 }
} 

Also, as they explain you already a transaction cannot start inside the same service. So if you want to make first method transactional you must invoke from outside of your service.