|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Copyright 2002-2018 the original author or authors. |
|
|
|
* Copyright 2002-2023 the original author or authors. |
|
|
|
* |
|
|
|
* |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -21,6 +21,7 @@ import java.sql.SQLException; |
|
|
|
|
|
|
|
|
|
|
|
import jakarta.persistence.EntityManager; |
|
|
|
import jakarta.persistence.EntityManager; |
|
|
|
import jakarta.persistence.PersistenceException; |
|
|
|
import jakarta.persistence.PersistenceException; |
|
|
|
|
|
|
|
import org.eclipse.persistence.sessions.DatabaseLogin; |
|
|
|
import org.eclipse.persistence.sessions.UnitOfWork; |
|
|
|
import org.eclipse.persistence.sessions.UnitOfWork; |
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.jdbc.datasource.ConnectionHandle; |
|
|
|
import org.springframework.jdbc.datasource.ConnectionHandle; |
|
|
|
@ -31,8 +32,7 @@ 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). Developed and tested against EclipseLink 2.7; |
|
|
|
* Persistence Services (EclipseLink). Compatible with EclipseLink 3.0/4.0. |
|
|
|
* backwards-compatible with EclipseLink 2.5 and 2.6 at runtime. |
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
* <p>By default, this class acquires an early EclipseLink transaction with an early |
|
|
|
* <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 |
|
|
|
* JDBC Connection for non-read-only transactions. This allows for mixing JDBC and |
|
|
|
@ -77,22 +77,40 @@ public class EclipseLinkJpaDialect extends DefaultJpaDialect { |
|
|
|
public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition) |
|
|
|
public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition) |
|
|
|
throws PersistenceException, SQLException, TransactionException { |
|
|
|
throws PersistenceException, SQLException, TransactionException { |
|
|
|
|
|
|
|
|
|
|
|
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { |
|
|
|
int currentIsolationLevel = definition.getIsolationLevel(); |
|
|
|
|
|
|
|
if (currentIsolationLevel != TransactionDefinition.ISOLATION_DEFAULT) { |
|
|
|
// Pass custom isolation level on to EclipseLink's DatabaseLogin configuration
|
|
|
|
// Pass custom isolation level on to EclipseLink's DatabaseLogin configuration
|
|
|
|
// (since Spring 4.1.2)
|
|
|
|
// (since Spring 4.1.2 / revised in 5.3.28)
|
|
|
|
UnitOfWork uow = entityManager.unwrap(UnitOfWork.class); |
|
|
|
UnitOfWork uow = entityManager.unwrap(UnitOfWork.class); |
|
|
|
uow.getLogin().setTransactionIsolation(definition.getIsolationLevel()); |
|
|
|
DatabaseLogin databaseLogin = uow.getLogin(); |
|
|
|
|
|
|
|
// Synchronize on shared DatabaseLogin instance (-> concurrent transactions)
|
|
|
|
|
|
|
|
synchronized (databaseLogin) { |
|
|
|
|
|
|
|
int originalIsolationLevel = databaseLogin.getTransactionIsolation(); |
|
|
|
|
|
|
|
// Apply current isolation level value, if necessary.
|
|
|
|
|
|
|
|
if (currentIsolationLevel != originalIsolationLevel) { |
|
|
|
|
|
|
|
databaseLogin.setTransactionIsolation(currentIsolationLevel); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Transaction begin including enforced JDBC Connection access
|
|
|
|
|
|
|
|
// (picking up current isolation level from DatabaseLogin)
|
|
|
|
|
|
|
|
entityManager.getTransaction().begin(); |
|
|
|
|
|
|
|
uow.beginEarlyTransaction(); |
|
|
|
|
|
|
|
entityManager.unwrap(Connection.class); |
|
|
|
|
|
|
|
// Restore original isolation level value, if necessary.
|
|
|
|
|
|
|
|
if (currentIsolationLevel != originalIsolationLevel) { |
|
|
|
|
|
|
|
databaseLogin.setTransactionIsolation(originalIsolationLevel); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
entityManager.getTransaction().begin(); |
|
|
|
entityManager.getTransaction().begin(); |
|
|
|
|
|
|
|
if (!definition.isReadOnly() && !this.lazyDatabaseTransaction) { |
|
|
|
if (!definition.isReadOnly() && !this.lazyDatabaseTransaction) { |
|
|
|
// Begin an early transaction to force EclipseLink to get a JDBC Connection
|
|
|
|
// Begin an early transaction to force EclipseLink to get a JDBC Connection
|
|
|
|
// so that Spring can manage transactions with JDBC as well as EclipseLink.
|
|
|
|
// so that Spring can manage transactions with JDBC as well as EclipseLink.
|
|
|
|
entityManager.unwrap(UnitOfWork.class).beginEarlyTransaction(); |
|
|
|
entityManager.unwrap(UnitOfWork.class).beginEarlyTransaction(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return null; |
|
|
|
return entityManager; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
|