EclipseLinkJpaDialect applies per-transaction isolation level to shared DatabasePlatform
See original GitHub issuespring orm version: 5.1.4.RELEASE
In EclipseLinkJpaDialect class line 81
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
// Pass custom isolation level on to EclipseLink's DatabaseLogin configuration
// (since Spring 4.1.2)
UnitOfWork uow = entityManager.unwrap(UnitOfWork.class);
uow.getLogin().setTransactionIsolation(definition.getIsolationLevel());
}
for instance: If txA beginTransaction and there is Isolation.SERIALIZABLE around the repository class, the TransactionIsolation in uow.getLogin() will be changed to Isolation.SERIALIZABLE. Then txB beginTransaction with Isolation.DEFAULT, the condition is not met, TransactionIsolation in uow.getLogin() still be SERIALIZABLE.
I think the right code should like this:
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT
&& definition.getIsolationLevel() != entityManager.unwrap(UnitOfWork.class).getLogin().setTransactionIsolation()) {
// ...
}
Issue Analytics
- State:
- Created 3 years ago
- Comments:13 (8 by maintainers)
Top Results From Across the Web
Spring managed transactions, EclipseLink JPA, custom ...
Configure the database transaction isolation as serializable. Configure objects as isolated (see Configuring Cache Isolation at the Project Level or Configuring ...
Read more >EclipseLinkJpaDialect (Spring Framework 6.0.2 API)
This allows for reusing the same JDBC Connection throughout an entire EclipseLink transaction, for enforced isolation and consistent visibility with JDBC access ...
Read more >A beginner's guide to transaction isolation levels in enterprise ...
All databases allow you to set the default transaction isolation level. Typically, the database is shared among multiple applications and ...
Read more >Spring managed transactions, EclipseLink JPA, custom ...
EclipseLinkJpaDialect#beginTransaction does not support any transaction isolation level but the default. So then I tried getting to ...
Read more >Need custom isolation level for OpenJPA (DB2Dialect) - IBM
Any guidelines to have DB2 spesific isolation support on OpenJPA ? ... Seems like the 'problem' is that isolationLevel does not apply on...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
transactionIsolation field in org.eclipse.persistence.internal.databaseaccess.DatabasePlatform is not synchronized. This is the root cause.
DatabasePlatform stores various database settings that rarely change at runtime. Perhaps that is what implementors of EclipseLink meant for transactionIsolation as well, set it once and forget. This is how most database applications use it anyway. It is rare for an application to use transaction isolation level other than the default.
An instance of this class is called by JpaTransactionManager which is a Spring bean in our application. Application accesses this bean from multiple threads. Now you can imagine multiple service threads starting transactions with different isolation levels concurrently. Also statement in EclipseLinkAdapter.beginTransaction() checks requested transaction isolation level and simply returns without setting it if it is equal to a default value. Transaction isolation level is set to default automatically in Spring if it is not set explicitly. In majority of our usages, we don’t set this level explicitly for one simple reason - default isolation level READ_COMMITTED is sufficient for our purposes most of the time. However it means that transaction by explicitly setting non-default isolation level overrides this level for all subsequent transactions. Not only that, depending on timing, a transaction in one thread could silently override transaction isolation level in another thread.
To remedy this problem I supplied CustomOraclePlatform bean where I override setTransactionIsolation() and getTransactionIsolation(). These methods make use of a ThreadLocal field represeting isolation level. Now each thread gets its own isolation level. However transactions with different isolation levels in the same thread would still experience the problem. Also cached thread pools do not reset ThreadLocals. For that we need to prevent EclipseLinkJpaDialect from invoking short-circuit check for default level. This can be be done by translating TransactionDefinition.ISOLATION_DEFAULT to TransactionDefinition.ISOLATION_READ_COMMITTED (or whatever default level is appropriate for your database) in EclipseLinkJpaDialect.beginTransaction(). This is exactly what I did in CustomEclipseLinkJpaDialect.
We could try to operate directly on the JDBC Connection but we’d have to clarify when exactly an EclipseLink Session obtains its JDBC Connection and when exactly it returns the Connection to the pool. Hibernate has well-defined connection policies for that purpose, whereas with EclipseLink we’d probably have to rely on implementation behavior (hoping that it won’t change).