您可以在一个休眠会话中拥有多个事务吗?

您可以在一个休眠会话中拥有多个事务吗?

我不清楚这是否是一个允许的可取的。在我的代码中,我有一个长时间运行的线程,并从阻塞队列中获取项目,根据队列上的内容,它可能需要创建并保存休眠对象,或者它可能不需要执行任何操作。

每个项目都是不同的,因此,如果项目 1 已保存,而项目 2 无法保存,则我不想这样做,以防止将项目 1 添加到数据库中。

因此,最简单的方法是针对需要创建的每个项目创建新会话,打开事务,保存新对象,提交事务,关闭会话

但是,这意味着为每个项目创建一个新会话,这似乎违背了Hibernates自己的建议,即不按请求模式执行会话。所以我的替代方案是在线程中创建一个会话,然后在需要时打开并提交一个新事务来创建新对象。但是我没有看到这种方法的例子,我不确定它是否真的有效。


答案 1

如果运行本地事务,则每个请求的会话模式每个会话使用一个 JDBC 连接。对于 JTA,连接在每个语句之后都会主动释放,只是为了在下一个语句中重新获取。

休眠事务 API 将开始/提交/回滚委托给 JDBC 连接以进行本地事务,并将关联的 UserTransaction 委托给 JTA。因此,您可以在同一休眠会话上运行多个事务,但有一个问题。一旦引发异常,您将无法再重用该会话。

我的建议是分而治之。只需拆分所有项目,为每个项目构造一个 Command 对象,并将它们发送到 ExecutorService#invokeAll。使用返回的 List 进行迭代并调用 Future#get() 以确保原始线程在所有批处理作业完成后等待。

将确保您同时运行所有命令,并且每个命令都应使用使用其自己的 .由于事务是线程绑定的,因此所有批处理作业都将单独运行ExecutorService@Transaction


答案 2

显然,你可以。休眠会话或多或少是数据库连接和数据库对象的缓存。您可以在单个数据库连接中拥有多个连续的事务。此外,使用连接池时,连接不会关闭,而是会回收。

是否应该重用会话中的对象。如果很有可能,但您可以重用先前事务放入会话中的对象,则应为多个事务保留一个会话。但是,如果一旦提交了一个对象,它将永远不会被重用,那么关闭会话并重新打开一个新会话,或者只是清除它当然更好。

怎么做 :

如果您有一个 Session 对象,则可以使用 以下列方式创建事务:

Transaction transaction;
transaction = session.beginTransaction();
... (operations in the context of transaction)
transaction.commit();
... (other commands outside of any transaction)
transaction = session.beginTransaction();
... (and so on and so forth ...)

推荐