|
|
|
@ -34,14 +34,20 @@ import org.springframework.transaction.TransactionException; |
|
|
|
* {@link org.springframework.orm.jpa.JpaDialect} implementation for Eclipse |
|
|
|
* {@link org.springframework.orm.jpa.JpaDialect} implementation for Eclipse |
|
|
|
* Persistence Services (EclipseLink). Compatible with EclipseLink 3.0/4.0. |
|
|
|
* Persistence Services (EclipseLink). Compatible with EclipseLink 3.0/4.0. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>By default, this class acquires an early EclipseLink transaction with an early |
|
|
|
* <p>By default, this dialect acquires an early EclipseLink transaction with an |
|
|
|
* JDBC Connection for non-read-only transactions. This allows for mixing JDBC and |
|
|
|
* early JDBC Connection for non-read-only transactions. This allows for mixing |
|
|
|
* JPA/EclipseLink operations in the same transaction, with cross visibility of |
|
|
|
* JDBC and JPA operations in the same transaction, with cross visibility of |
|
|
|
* their impact. If this is not needed, set the "lazyDatabaseTransaction" flag to |
|
|
|
* their impact. If this is not needed, set the "lazyDatabaseTransaction" flag to |
|
|
|
* {@code true} or consistently declare all affected transactions as read-only. |
|
|
|
* {@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 |
|
|
|
* As of Spring 4.1.2, this will reliably avoid early JDBC Connection retrieval |
|
|
|
* and therefore keep EclipseLink in shared cache mode. |
|
|
|
* 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 |
|
|
|
* @author Juergen Hoeller |
|
|
|
* @since 2.5.2 |
|
|
|
* @since 2.5.2 |
|
|
|
* @see #setLazyDatabaseTransaction |
|
|
|
* @see #setLazyDatabaseTransaction |
|
|
|
@ -65,7 +71,16 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect { |
|
|
|
* even for non-read-only transactions, allowing access to EclipseLink's |
|
|
|
* even for non-read-only transactions, allowing access to EclipseLink's |
|
|
|
* shared cache and following EclipseLink's connection mode configuration, |
|
|
|
* shared cache and following EclipseLink's connection mode configuration, |
|
|
|
* assuming that isolation and visibility at the JDBC level are less important. |
|
|
|
* 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 org.eclipse.persistence.sessions.UnitOfWork#beginEarlyTransaction() |
|
|
|
|
|
|
|
* @see TransactionDefinition#isReadOnly() |
|
|
|
|
|
|
|
* @see TransactionDefinition#getIsolationLevel() |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void setLazyDatabaseTransaction(boolean lazyDatabaseTransaction) { |
|
|
|
public void setLazyDatabaseTransaction(boolean lazyDatabaseTransaction) { |
|
|
|
this.lazyDatabaseTransaction = lazyDatabaseTransaction; |
|
|
|
this.lazyDatabaseTransaction = lazyDatabaseTransaction; |
|
|
|
@ -83,7 +98,8 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect { |
|
|
|
// (since Spring 4.1.2 / revised in 5.3.28)
|
|
|
|
// (since Spring 4.1.2 / revised in 5.3.28)
|
|
|
|
UnitOfWork uow = entityManager.unwrap(UnitOfWork.class); |
|
|
|
UnitOfWork uow = entityManager.unwrap(UnitOfWork.class); |
|
|
|
DatabaseLogin databaseLogin = uow.getLogin(); |
|
|
|
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) { |
|
|
|
synchronized (databaseLogin) { |
|
|
|
int originalIsolationLevel = databaseLogin.getTransactionIsolation(); |
|
|
|
int originalIsolationLevel = databaseLogin.getTransactionIsolation(); |
|
|
|
// Apply current isolation level value, if necessary.
|
|
|
|
// Apply current isolation level value, if necessary.
|
|
|
|
@ -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 { |
|
|
|
else { |
|
|
|
|
|
|
|
// Regular transaction begin with lazy database transaction.
|
|
|
|
entityManager.getTransaction().begin(); |
|
|
|
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; |
|
|
|
return null; |
|
|
|
|