@ -34,14 +34,20 @@ import org.springframework.transaction.TransactionException;
@@ -34,14 +34,20 @@ import org.springframework.transaction.TransactionException;
* { @link org . springframework . orm . jpa . JpaDialect } implementation for Eclipse
* Persistence Services ( EclipseLink ) . Compatible with EclipseLink 3 . 0 / 4 . 0 .
*
* < p > By default , this class acquires an early EclipseLink transaction with an early
* JDBC Connection for non - read - only transactions . This allows for mixing JDBC and
* JPA / EclipseLink operations in the same transaction , with cross visibility of
* < p > By default , this dialect acquires an early EclipseLink transaction with an
* early JDBC Connection for non - read - only transactions . This allows for mixing
* JDBC and JPA operations in the same transaction , with cross visibility of
* their impact . If this is not needed , set the "lazyDatabaseTransaction" flag to
* { @code true } or consistently declare all affected transactions as read - only .
* As of Spring 4 . 1 . 2 , this will reliably avoid early JDBC Connection retrieval
* and therefore keep EclipseLink in shared cache mode .
*
* < p > < b > NOTE : This dialect supports custom isolation levels with limitations . < / b >
* Consistent isolation level handling is only guaranteed when all Spring transaction
* definitions specify a concrete isolation level , and as of 6 . 0 . 10 also when using
* the default isolation level with non - readOnly and non - lazy transactions . See the
* { @link # setLazyDatabaseTransaction "lazyDatabaseTransaction" javadoc } for details .
*
* @author Juergen Hoeller
* @since 2 . 5 . 2
* @see # setLazyDatabaseTransaction
@ -65,7 +71,16 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect {
@@ -65,7 +71,16 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect {
* even for non - read - only transactions , allowing access to EclipseLink ' s
* shared cache and following EclipseLink ' s connection mode configuration ,
* assuming that isolation and visibility at the JDBC level are less important .
* < p > < b > NOTE : Lazy database transactions are not guaranteed to work reliably
* in combination with custom isolation levels . Use read - only as well as this
* lazy flag with care . If other transactions use custom isolation levels ,
* it is not recommended to use read - only and lazy transactions at all . < / b >
* Otherwise , you may see non - default isolation levels used during read - only
* or lazy access . If this is not acceptable , don ' t use read - only and lazy
* next to custom isolation levels in potentially concurrent transactions .
* @see org . eclipse . persistence . sessions . UnitOfWork # beginEarlyTransaction ( )
* @see TransactionDefinition # isReadOnly ( )
* @see TransactionDefinition # getIsolationLevel ( )
* /
public void setLazyDatabaseTransaction ( boolean lazyDatabaseTransaction ) {
this . lazyDatabaseTransaction = lazyDatabaseTransaction ;
@ -83,7 +98,8 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect {
@@ -83,7 +98,8 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect {
// (since Spring 4.1.2 / revised in 5.3.28)
UnitOfWork uow = entityManager . unwrap ( UnitOfWork . class ) ;
DatabaseLogin databaseLogin = uow . getLogin ( ) ;
// Synchronize on shared DatabaseLogin instance (-> concurrent transactions)
// Synchronize on shared DatabaseLogin instance for consistent isolation level
// set and reset in case of concurrent transactions with different isolation.
synchronized ( databaseLogin ) {
int originalIsolationLevel = databaseLogin . getTransactionIsolation ( ) ;
// Apply current isolation level value, if necessary.
@ -101,13 +117,23 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect {
@@ -101,13 +117,23 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect {
}
}
}
else if ( ! definition . isReadOnly ( ) & & ! this . lazyDatabaseTransaction ) {
// Begin an early transaction to force EclipseLink to get a JDBC Connection
// so that Spring can manage transactions with JDBC as well as EclipseLink.
UnitOfWork uow = entityManager . unwrap ( UnitOfWork . class ) ;
DatabaseLogin databaseLogin = uow . getLogin ( ) ;
// Synchronize on shared DatabaseLogin instance for consistently picking up
// the default isolation level even in case of concurrent transactions with
// a custom isolation level (see above), as of 6.0.10
synchronized ( databaseLogin ) {
entityManager . getTransaction ( ) . begin ( ) ;
uow . beginEarlyTransaction ( ) ;
entityManager . unwrap ( Connection . class ) ;
}
}
else {
// Regular transaction begin with lazy database transaction.
entityManager . getTransaction ( ) . begin ( ) ;
if ( ! definition . isReadOnly ( ) & & ! this . lazyDatabaseTransaction ) {
// Begin an early transaction to force EclipseLink to get a JDBC Connection
// so that Spring can manage transactions with JDBC as well as EclipseLink.
entityManager . unwrap ( UnitOfWork . class ) . beginEarlyTransaction ( ) ;
}
}
return null ;