1

As per my understanding, private methods can't be proxied in Spring Boot. And thus @Transactional can't be put on private methods. Which makes me wonder, can transaction propagate if there are one or more private methods in between e.g. are the following code blocks equivalent:

class SomeClass{

@Autowired Dao dao;
 
@Transactional(propagation = Propagation.REQUIRED)
public bigMethod(int someArgument){
  Data data1 = process(someArgument);
  Data data2 = process(someArgument+1);
  this.dao.save(data1);
  this.dao.save(data2);
}

}

Is the above equivalent to:

class SomeClass{

    @Autowired Dao dao;

    @Transactional(propagation = Propagation.REQUIRED)
    public bigMethod(int someArgument){
      Data data1 = process(someArgument);
      Data data2 = process(someArgument+1);
      doSave(data1);
      doSave(data2);
    }
    
    private void doSave(Data data){
     this.dao.save(data);
    }

Notice the the second code adds a private method in between. And the dao.save() method which is in a separate class is as:

public class DAO{
 @Autowired Repository repo;
 @Transactional(propagation = Propagation.REQUIRED)   
  public void save(Data data){
  repo.save(data);
  }
 }
Ravi Shekhar
  • 78
  • 10
  • manage you trx manual, ref: https://stackoverflow.com/questions/26606608/how-to-manually-start-a-transaction-on-a-shared-entitymanager-in-spring – 袁文涛 Sep 02 '21 at 06:32
  • It doesn't matter since both versions won't work correctly. The save function must be in another Bean, it can't be in the same bean anyway, because Spring cannot insert itself between java to java function calls in the same class. – Gonen I Sep 02 '21 at 06:36
  • @GonenI, the dao.save() is in a separate class. I will just edit my question to reflect that. – Ravi Shekhar Sep 02 '21 at 06:39
  • in that case you will have to have a reference to the bean of that other class, and the private function in the middle will make no difference. – Gonen I Sep 02 '21 at 06:40
  • @GonenI, yeah I just kept parts of code which were relevant. Anyways thanks. – Ravi Shekhar Sep 02 '21 at 06:42

1 Answers1

1

In order for Spring to give you services such as transaction propagation it needs to be able to intercept or "insert itself" between the calls.

When you call dao.bigMethod the dao object is not really an instance of the Dao class, but is in fact a Spring AOP proxy to the Dao class, that also has a bigMethod function. When you call the bigMethod on the AOP proxy Spring adds its services, such as transactions, and then calls the your bigMethod class.

Once you are in your bigMethod function, you are just in a regular Java function and Spring cannot see any function calls that you make. Because of that, if inside bigMethod you call another Java function such as save, Spring will not see it, and cannot add any more transaction services.

To get further services from Spring you must move save to another bean , and get a handle to that bean, which will once again be to an AOP proxy of the class that contains save.

Once you have that AOP proxy, when you call it Spring will give you transaction services again, even if the point of the call is inside a private function.

Gonen I
  • 5,576
  • 1
  • 29
  • 60