将JPA和JDBC操作组合在一个事务中



因此,我有一个应用程序,其中包含一些遗留JDBC调用,需要使用一些额外的JPA操作进行更新。我需要能够将JDBC调用和JPA调用作为同一DB事务的一部分。如果重要的话,我使用的是OpenJPA 2.1.1和Postgres 9.1。下面的代码似乎工作正常——我已经运行了一些基本测试,JDBC和JPA语句都执行了;其中任何一个错误都会导致这对语句不发生(例如,它们是同一DB事务的一部分)。它是否有任何我没有看到的问题——我违反了一些最佳实践,或者我不能以这种方式重用Connection对象的其他原因?

EntityManager em = _em; //acquired from OpenJPA
em.getTransaction().begin();
Connection conn;
try {
OpenJPAEntityManager oem = (OpenJPAEntityManager) em.getDelegate();
conn = oem.getConnection();
PreparedStatement ps = conn.prepareStatement(myStatement);
//initialize parameters in ps
ps.executeUpdate();
em.merge(myJpaObject);
em.getTransaction().commit();
} finally {
if (ps != null && !ps.isClosed()) {
ps.close();
}
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
}

谢谢!

只要做一个调整,我认为这应该没问题。

值得注意的是,OpenJPA文档对它的描述是:

只有当EntityManager处于托管或非乐观事务中,如果EntityManager已在当前事务中刷新,或者您已使用OpenJPAEntityManager.beginStore方法来确保数据存储事务正在进行时,才保证返回的连接与其他EntityManager操作在事务上一致。在尝试任何其他EntityManager操作之前,请始终关闭返回的连接。如果数据存储事务正在进行,OpenJPA将确保底层本机连接不会被释放。

您的交易没有得到管理,但我认为这是不乐观的。此外,在启动事务和执行JDBC之间,您还没有完成任何JPA工作,所以我认为您可能属于"如果EntityManager已在当前事务中刷新"的情况。

您没有做的一件事是在继续使用JPA之前关闭连接。我假设OpenJPA不会返回它正在使用的实际连接,而是一些包装器,应该在OpenJPA恢复工作之前关闭它。

最新更新