在 Hibernate 事务中执行 jOOQ 语句

Posted

技术标签:

【中文标题】在 Hibernate 事务中执行 jOOQ 语句【英文标题】:Executing jOOQ statements inside Hibernate transaction 【发布时间】:2020-12-20 12:24:27 【问题描述】:

假设我同时使用 Hibernate (JPA) 和 jOOQ 来实现数据持久性。

我想通过 EntityManager 打开事务来做一些工作。

然后我使用 jOOQ 在我用 EntityManager 打开的同一个事务中选择和更新几个表,然后我提交或回滚上述所有操作。

我不使用 Spring 或任何其他容器事务管理器。

try 
    entityManager.getTransaction().begin();
    //do JPA stuff here fetch from FB update entity
    DLSConext - want to use JOOQ DSL for crud operation
    em.getTransaction().commit()
 catch (Exception e) 
    em.getTransaction().rollback();  //All Hibernate and jooq operation should rool back

编辑 那么我该怎么做呢? 例如,我使用 jOOQ 进行一些更新,然后我希望 Hibernate 找到一个实体,但我还希望 Hibernate 在获取实体之前看到 jOOQ 完成的几行更新。

【问题讨论】:

您可能需要检查 ***.com/questions/3493495/… 。我仍然建议你不要走这条路。混合使用 JPA/ORM 和原始 SQL./JDBC 对您的缓存(会话本身、L2 缓存、查询缓存)不利,并且会导致非常难以调试的问题,除非您确定您没有在“后面”操作/刷新数据JPA/Hibernate 的背面”,这在你做的时候很难证明,而且在未来的演变中也更难强制执行。 你的问题是什么? 我编辑了我的问题 【参考方案1】:

这并不是真正特定于 jOOQ,而是适用于 JPA 与本机 SQL 的所有混合。在运行任何 jOOQ(或 JDBC 等)查询之前,您必须确保所有 Hibernate 的缓存都已刷新。

如果您直接使用 jOOQ 执行查询,您可以在 jOOQ 的 ConnectionProvider SPI 中执行此操作,每次 jOOQ 想要执行查询之前都会调用它。或者,也可以像这样使用 Hibernate 的 Session.doWork() API:

public static Work jOOQWork(Session session, Consumer<DSLContext> consumer) 
    session.flush();
    session.doWork(connection -> consumer.accept(DSL.using(connection)));

然后:

jOOQWork(session, ctx -> 
    ctx.insertInto(TABLE)
       .columns(TABLE.COL)
       .values(1)
       .execute()
);

请注意这里需要Session.flush(),尽管它可能不应该是,请参阅https://hibernate.atlassian.net/browse/HHH-14209

如果您通过EntityManager::createNativeQueryEntityManager::flushshould be called automatically for you 执行查询。

【讨论】:

谢谢。每次打开 Hibernate 会话时都需要设置 jooq 的 connectionProvider 吗?是否也意味着 jooq 的执行与我从 Hibernate 开始的事务在同一个事务中? @user1409534:嗯,你可以从 Hibernate 获得一个 JDBC 连接,参见***.com/q/3526556/521799。然后在 jOOQ 中用DSL.using(connection) 包装它,并确保获取 JDBC 连接的逻辑负责刷新... @user1409534:我已经用一个例子更新了我的答案

以上是关于在 Hibernate 事务中执行 jOOQ 语句的主要内容,如果未能解决你的问题,请参考以下文章

JOOQ:单个语句是隐式事务性的,还是我仍然必须将其包装在事务性块中?

jOOQ 和 Spring 事务管理

Hibernate-事务理解

hibernate事务管理

如何查看 jOOQ 在编译时执行的 SQL 语句?

在 JOOQ 中,如果我直接使用底层连接,我的事务状态是不是保持不变?