Just to understand the workings of Spring transactions I want to know what happens in the following case where one method marked as @Transactional
calls another method marked as @Transactional
.
Assume a the configuration uses all default settings.
@Service("myService")
@Transactional
public MyService{
public void myServiceMethod(){
myDAO.getSomeDBObjects();
}
}
@Repository("myDAO")
@Transactional
public MyDAOWithUsesBeyondMyService{
public void getSomeDBObjects(){...}
}
Now if I were to enter MyService.myServiceMethod()
it would clearly start a transaction. Then, upon drilling into myDAO.getSomeDBObjects()
what would happen? Would the fact that a transaction already exist cause no new transaction to be born, or am I creating two transactions here?
The documentation (quoted below) on Propagation seems to cover this, but I'd like to verify my understanding, it was a little much for my virgin brain to comprehend all at once.
Propagation: 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 Section
10.5.7, “Transaction propagation”.
Best Answer
Two answers:
a) don't do it. Use
@Transactional
in the service layer or the dao layer, but not both (the service layer is the usual choice, as you probably want one transaction per service method)b) if you do it, what happens depends on the
propagation
attribute of the@Transactional
annotation and is described in this section: 10.5.7 Transaction propagation. Basically:PROPAGATION_REQUIRED
means the same transaction will be used for both methods, whilePROPAGATION_REQUIRES_NEW
starts a new transaction.About your comments:
That's not true in your situation (only if both methods were within the same class).
If a bean has methods
a
andb
, anda
callsb
, thenb
is called on the actual method, not the proxy, because it is called from within the proxy (a bean doesn't know that it is proxied to the outside world).In your situation, however, a service would have an injected dao object, which would be a proxy itself, so you'd have a situation like this: