你能在一个Hibernate会话中拥有多个交易吗?

时间:2014-09-17 14:34:14

标签: java database hibernate session transactions

你能在一个Hibernate会话中拥有多个交易吗?

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

每个项目都是不同的,所以如果项目1被保存,项目2无法保存我不想要的任何原因,以防止项目1被添加到数据库中。

所以最简单的方法是为需要创建的每个项创建一个新会话,打开事务,保存新对象,提交事务,关闭会话

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

5 个答案:

答案 0 :(得分:26)

如果运行本地事务,则每个会话的会话模式会在每个会话中使用一个JDBC连接。对于JTA,只有在下一个语句重新获取时才会在每个语句之后积极地释放连接。

Hibernate transaction API delegates the begin/commit/rollback to the JDBC Connection for local transactions and to the associated UserTransaction for JTA。因此,您可以在同一个Hibernate会话上运行多个事务,但是有一个问题。抛出异常后,您将无法再重用该会话。

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

ExecutorService将确保您同时运行所有命令,并且每个Command应使用使用其自己的@Transaction的服务。由于事务是线程绑定的,因此您将拥有所有batch jobs run in isolation

答案 1 :(得分:12)

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

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

怎么做:

如果您有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 ...)

答案 2 :(得分:3)

来自hibernates文档

"会话是一种廉价的非线程安全对象,应该使用一次然后丢弃,用于:单个请求,对话或单个工作单元。除非需要,否则会话将不会获取JDBC连接或数据源。在使用之前,它不会消耗任何资源。"

因此,如果您一次又一次地创建会话,则不会给系统带来太大负担。如果你继续会话的时间太长,可能会产生问题,因为会话不是线程安全的。在我看来,最简单的解决方案是最好的"所以最简单的方法是为每个需要创建的项目创建一个新会话,打开事务,保存新对象,提交事务,关闭会话"

顺便说一句,如果你创建任何事情的单一记录,你就不需要太多的交易。创造单一记录本身就是"全部或全部没有#34;我们使用交易的东西

答案 3 :(得分:0)

简短回答是肯定的,您可以使用相同的会话进行交易。看看org.hibernate.Transaction。,它需要管理事务的方法。

答案 4 :(得分:0)

a=matrix([[1,2,3],
          [8,2,9],
          [1,8,7]])

row = [1,2,3]
col = [[1,2]
       [1,3]
       [2,3]]