在JPA / EclipsLink EntityManager中更改隔离级别后清理

时间:2016-01-14 17:55:36

标签: java jpa transactions eclipselink

我使用自定义事务隔离级别在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);

如果我在提交事务后尝试将隔离级别重置为旧值,则基础连接为空(entityManager.unwrap(Connection.class)返回null)。我很担心,如果我不重置隔离级别,隔离级别较差的连接会泄漏回池中。

更改隔离级别后清理的正确方法是什么?我应该在调用commit()之前这样做吗?

2 个答案:

答案 0 :(得分:1)

在调用java.sql.Connection时,entityManager.getTransaction().commit();将返回到池中。因此,EclipseLink无法通过返回null连接来阻止隔离级别。

保持对Connection的引用以避免这种情况可能会泄漏与更改设置的连接,因此我无法接受您的答案RomanC

我最终创建了EntityManagerFactory的两个实例。一个创建默认EntityManagers,另一个使用EntityManagers创建SessionCustomizer与我的所需交易级别的连接:

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);
}

请参阅此处Set Isolation level in eclipselink

然后我使用提供我需要的任何连接类型的EntityManagerFactory。警告:交易不能跨越多个EntityManagers

EntityManagerFactories

答案 1 :(得分:0)

尝试以下代码

Connection conn = entityManager.unwrap(Connection.class);

conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);

[...Queries...]

// commit transaction
entityManager.getTransaction().commit();

conn.setTransactionIsolation(isolationLevelOld);