Reputation: 2014
I've got in my project code similar to this
@Transactional(readOnly = true)
public void tt() {
dd();
}
@Transactional()
public void dd() {
gg();
}
@Transactional(readOnly = true)
public void gg() {
}
Function dd is used both by other readonly transaction functions and not readonly functions. Assuming that transaction should extendend from execution of tt to gg - operations in dd will in be read-only transaction or not?
Upvotes: 2
Views: 7496
Reputation: 27614
In this particular example, your question is moot.
The call to dd()
from tt()
will not pass the proxy boundary so no transactional advise will be applied to dd()
(since it's a call inside the same instance). Same with the call to gg()
from dd()
. Consequently, only the call from outside to tt()
would actually be transaction-advised (in your case, with readOnly=true
) and that would be the transaction that would be used in the entire call-chain.
In the general case though, read the documentation hinted by @melihcelik - it explains the behavior.
Upvotes: 6
Reputation: 4599
Spring's AbstractPlatformTransactionManager
has a property named validateExistingTransaction
that controls this behavior. Javadoc states that:
When participating in an existing transaction (e.g. with PROPAGATION_REQUIRES or PROPAGATION_SUPPORTS encountering an existing transaction), this outer transaction's characteristics will apply even to the inner transaction scope. Validation will detect incompatible isolation level and read-only settings on the inner transaction definition and reject participation accordingly through throwing a corresponding exception.
Since default propagation for Spring @Transactional
annotation is REQUIRED
and default validation strategy is false, I expect Spring to use existing transaction created from tt
method call in readonly mode.
If you want to have a read only transaction, then you have to annotate your method with:
@Transactional(propagation=Propagation.REQUIRES_NEW, readOnly=true)
Upvotes: 3
Reputation: 47300
use @Transactional(readoOnly = true)
if you are performing a get/select and not making any changes, this means that no locks will be applied (which is more efficent).
For updates/inserts/deletions/saves/merges I use (when a lock is required) :
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
Upvotes: 3