5

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

谢谢!

4

1 回答 1

3

稍微调整一下,我认为应该没问题。

值得注意的是 OpenJPA 文档对此有何评论

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

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

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

于 2012-11-21T20:18:38.213 回答