mmatloka
mmatloka

Reputation: 2014

Transactions via spring annotations - readonly or not?

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

Answers (3)

pap
pap

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

melihcelik
melihcelik

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

NimChimpsky
NimChimpsky

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

Related Questions