在 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::createNativeQuery
、EntityManager::flush
should 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 语句的主要内容,如果未能解决你的问题,请参考以下文章