在 JPA / EclipsLink EntityManager 中更改隔离级别后进行清理
Cleaning up after changing the isolation level in JPA / EclipsLink EntityManager
我正在使用自定义事务隔离级别在 JPA (EclipseLink) 中执行事务,我使用以下代码在 JPA EntityManager
的基础连接上设置了该级别:
// begin transaction
entityManager.getTransaction().begin();
// store the old isolation level
int isolationLevelOld = entityManager.unwrap(Connection.class).getTransactionIsolation();
// set the desired isolation level for this transaction
entityManager.unwrap(Connection.class).setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
[...Queries...]
// commit transaction
entityManager.getTransaction().commit();
// reset isolation level to the old value (throws NullPointerException)
entityManager.unwrap(Connection.class).setTransactionIsolation(isolationLevelOld);
如果我在提交事务后尝试将隔离级别重置为旧值,则基础连接为 null
(entityManager.unwrap(Connection.class)
returns 空)。我担心,如果我不重置隔离级别,隔离级别不佳的连接会泄漏回池中。
更改隔离级别后正确的清理方法是什么?我应该在打电话给 commit()
之前做吗?
试试下面的代码
Connection conn = entityManager.unwrap(Connection.class);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
[...Queries...]
// commit transaction
entityManager.getTransaction().commit();
conn.setTransactionIsolation(isolationLevelOld);
java.sql.Connection
在对 entityManager.getTransaction().commit();
的调用中返回到池中,因此之后重置隔离级别是不可能的,并且 EclipseLink 通过返回 null
连接来阻止。
维护对 Connection
的引用以规避此问题可能会泄漏更改设置的连接,因此我不能接受您的回答 RomanC
我最终创建了 EntityManagerFactory
的两个实例。一种创建默认值 EntityManagers
,另一种使用 SessionCustomizer
:
创建 EntityManagers
与我想要的事务级别的连接
public static class SessionCustomizer implements org.eclipse.persistence.config.SessionCustomizer {
@Override
public void customize(Session session) throws Exception {
DatabaseLogin databaseLogin = (DatabaseLogin) session.getDatasourceLogin();
databaseLogin.setTransactionIsolation(DatabaseLogin.TRANSACTION_SERIALIZABLE);
}
}
private void init() {
entityManagerFactoryRegular = Persistence.createEntityManagerFactory("MyPersitenceRegular");
Map<String, String> props = new HashMap<>();
props.put(PersistenceUnitProperties.SESSION_CUSTOMIZER, SessionCustomizer.class.getName());
entityManagerFactoryTransactionSerializable = Persistence.createEntityManagerFactory("MyPersitenceTransactionSerializable", props);
}
看这里
然后我使用 EntityManagerFactory
提供我需要的任何连接类型。警告:交易不能跨越 EntityManagers
来自多个 EntityManagerFactories
我正在使用自定义事务隔离级别在 JPA (EclipseLink) 中执行事务,我使用以下代码在 JPA EntityManager
的基础连接上设置了该级别:
// begin transaction
entityManager.getTransaction().begin();
// store the old isolation level
int isolationLevelOld = entityManager.unwrap(Connection.class).getTransactionIsolation();
// set the desired isolation level for this transaction
entityManager.unwrap(Connection.class).setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
[...Queries...]
// commit transaction
entityManager.getTransaction().commit();
// reset isolation level to the old value (throws NullPointerException)
entityManager.unwrap(Connection.class).setTransactionIsolation(isolationLevelOld);
如果我在提交事务后尝试将隔离级别重置为旧值,则基础连接为 null
(entityManager.unwrap(Connection.class)
returns 空)。我担心,如果我不重置隔离级别,隔离级别不佳的连接会泄漏回池中。
更改隔离级别后正确的清理方法是什么?我应该在打电话给 commit()
之前做吗?
试试下面的代码
Connection conn = entityManager.unwrap(Connection.class);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
[...Queries...]
// commit transaction
entityManager.getTransaction().commit();
conn.setTransactionIsolation(isolationLevelOld);
java.sql.Connection
在对 entityManager.getTransaction().commit();
的调用中返回到池中,因此之后重置隔离级别是不可能的,并且 EclipseLink 通过返回 null
连接来阻止。
维护对 Connection
的引用以规避此问题可能会泄漏更改设置的连接,因此我不能接受您的回答 RomanC
我最终创建了 EntityManagerFactory
的两个实例。一种创建默认值 EntityManagers
,另一种使用 SessionCustomizer
:
EntityManagers
与我想要的事务级别的连接
public static class SessionCustomizer implements org.eclipse.persistence.config.SessionCustomizer {
@Override
public void customize(Session session) throws Exception {
DatabaseLogin databaseLogin = (DatabaseLogin) session.getDatasourceLogin();
databaseLogin.setTransactionIsolation(DatabaseLogin.TRANSACTION_SERIALIZABLE);
}
}
private void init() {
entityManagerFactoryRegular = Persistence.createEntityManagerFactory("MyPersitenceRegular");
Map<String, String> props = new HashMap<>();
props.put(PersistenceUnitProperties.SESSION_CUSTOMIZER, SessionCustomizer.class.getName());
entityManagerFactoryTransactionSerializable = Persistence.createEntityManagerFactory("MyPersitenceTransactionSerializable", props);
}
看这里
然后我使用 EntityManagerFactory
提供我需要的任何连接类型。警告:交易不能跨越 EntityManagers
来自多个 EntityManagerFactories