jpadilladev
jpadilladev

Reputation: 1936

@Transactional, method inside method

I have a Service with a method calling another method. In the first method, I perform only queries with SELECT, but they have to see the INSERTS and UPDATES done in the second method.

Then, I have to deal with transactions. I'm using Spring, so I can use the @Transactional annotation.

Which of the following options seems to be more correct for you?

Option A

@Transactional
public void generate(){
    // selects
    save(a);
    // more selects
}

@Transactional
public void save(Object a){
    //save the object
}

Option B

public void generate(){
    // selects
    save(a);
    // more selects
}

@Transactional
public void save(Object a){
    //save the object
}

Thanks!!

Upvotes: 7

Views: 17579

Answers (2)

Viswanath Lekshmanan
Viswanath Lekshmanan

Reputation: 10083

Ideal case should be

@Transactional
public void generate(){
    // selects
    save(a);
    // more selects
}

public void save(Object a){
    //save the object
}

That is transaction of generate method will be used. If any exception occured you can rollback all. If you want to override the behaviour. Use the propagation behaviour

E.g.:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void save(Object a){
    //save the object
}

Reference: Transaction propagation

Upvotes: 5

jpadilladev
jpadilladev

Reputation: 1936

I will answer myself after a bit of researching. Tell me something if you think I'm wrong :P

First of all, I think both options are correct, depending on your business logic. I mean, a method should be Transactional when it have to be all done in a same transaction, and this depends for the programmer and the business logic.

For example, Option A is correct if the 'generate' method contains logic to be done in the same Transaction, so if something in the generate method fails, all the changes are undone. In this case, the Transactional annotation in the save method is not necessary.

Option A

@Transactional
public void generate(){
    // selects
    save(a);
    // more selects
}

//@Transactional
public void save(Object a){
    //save the object
}

Option B is also correct if your Transaction, depending on your business logic, is only in the save method. But there is something wrong in Option B if you are using Spring and AOP (Aspects). Spring uses proxies when using AOP, so if you need to call a save method with a Transactional annotation, you have to use the proxy to let Spring call the save method within a Transaction.

Option B

private MyClass self; // this is the proxy bean of this class!

public void generate(){
    // selects
    self.save(a);
    // more selects
}

@Transactional
public void save(Object a){
    //save the object
}

Upvotes: 4

Related Questions