Skip to content

#3407 Honor isolation level on read-only transactions - #3874

Merged
rbygrave merged 1 commit into
ebean-orm:masterfrom
arimu1:fix/3407-readonly-isolation-level
Aug 14, 2026
Merged

#3407 Honor isolation level on read-only transactions#3874
rbygrave merged 1 commit into
ebean-orm:masterfrom
arimu1:fix/3407-readonly-isolation-level

Conversation

@arimu1

@arimu1 arimu1 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #3407 — when a method (or TxScope) is read-only and specifies an isolation level, Ebean dropped the isolation and always used the connection default (typically READ_COMMITTED).

Root cause

TransactionManager.createTransaction(TxScope) used the read-only path without applying isolation:

if (txScope.isReadonly()) {
  return createReadOnlyTransaction(null, false); // isolation ignored
} else {
  return createTransaction(true, txScope.getIsolationLevel());
}

Fix

After creating the read-only transaction, apply the same setIsolationLevel helper used by normal transactions:

if (txScope.isReadonly()) {
  SpiTransaction transaction = createReadOnlyTransaction(null, false);
  return transactionFactory.setIsolationLevel(transaction, txScope.getIsolationLevel());
}

When isolation is unset (-1), behavior is unchanged.

Tests

  • TestTransactionalReadOnly#test_readonly_honors_isolation — programmatic TxScope.required().setReadOnly(true).setIsolation(SERIALIZABLE)
  • TestTransactionalReadOnly#test_readonly_annotation_honors_isolation@Transactional(readOnly = true, isolation = SERIALIZABLE)
  • Existing read-only metric tests still pass
mvn -pl ebean-test -Dtest=org.tests.transaction.TestTransactionalReadOnly test
# Tests run: 4, Failures: 0 (Temurin 21, H2)

Notes

Isolation is still only as useful as the target database allows (e.g. some platforms map or reject READ_UNCOMMITTED). This change ensures the requested level is applied to the JDBC connection for read-only scopes when the platform supports it.

Read-only TxScope previously ignored isolation when creating
ImplicitReadOnlyTransaction. Apply setIsolationLevel after
createReadOnlyTransaction so @transactional(readOnly=true, isolation=...)
and TxScope setReadOnly+setIsolation take effect.
@rbygrave

rbygrave commented Aug 8, 2026

Copy link
Copy Markdown
Member

Do you have an application hitting this issue or is it more a bug fix for a known issue?

If you have an application hitting this, what database and isolation level is being used? Can you explain the use case? Do you have a workaround?

@arimu1

arimu1 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

@rbygrave Honest answer: I don't have a production app hitting this myself — the fix comes from the known issue #3407 reported by @rPraml.

Reporter's use case (from the issue): they hold update locks on certain tables and wanted some UI queries on a read-only connection at READ_UNCOMMITTED so the UI is less blocked. With @Transactional(readOnly = true, isolation = READ_UNCOMMITTED) they still got a read-only txn at the default isolation (READ_COMMITTED) because createReadOnlyTransaction never applied the requested isolation.

Workaround they used: skip the read-only connection (use a normal transaction) when a non-default isolation is required.

This PR: when TxScope requests both read-only and an isolation level, apply setIsolationLevel after creating the read-only transaction (same path as non-read-only scopes). Covered by TestTransactionalReadOnly for TxScope + @Transactional SERIALIZABLE on H2.

If you'd rather keep isolation unsupported on the read-only pool for product reasons (e.g. only useful on DB2), happy to close or narrow — just say the word.

@rbygrave

Copy link
Copy Markdown
Member

Hi @rPraml - I'm good with this PR and looking to merge. Note sure if you've had a look at it yet but if you can that would be great. For me this change is exactly what I expect.

Thanks, Rob.

@rPraml

rPraml commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

LGTM

@rbygrave
rbygrave merged commit 1c857e4 into ebean-orm:master Aug 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ReadOnly transactions does not honor isolation-level

3 participants