Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@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!!

like image 885
jpadilladev Avatar asked Feb 24 '16 12:02

jpadilladev


People also ask

Can we use @transactional on private method?

The answer your question is no - @Transactional will have no effect if used to annotate private methods. The proxy generator will ignore them. When using proxies, you should apply the @Transactional annotation only to methods with public visibility.

Can we use @transactional in service layer?

You should use @Transactional at service layer, if you want to change the domain model for client B where you have to provide the same data in a different model,you can change the domain model without impacting the DAO layer by providing a different service or by creating a interface and implementing the interface in ...

What happens if a method annotated with @transactional calls another method annotated with transactional?

If you call a method with a @Transactional annotation from a method with @Transactional belonging to the same Spring Bean , then the called methods transactional behavior will not have any impact on the transaction.

Can we use @transactional in interface?

You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies.


2 Answers

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

like image 63
Viswanath Lekshmanan Avatar answered Oct 20 '22 15:10

Viswanath Lekshmanan


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
}
like image 26
jpadilladev Avatar answered Oct 20 '22 14:10

jpadilladev