Hibernate SaveOrUpdate - 多个工作线程

时间:2013-10-23 21:25:35

标签: java database hibernate

虽然我已经能够找到有关Hibernate的事务如何工作的信息,因此数据库没有损坏,但是很难理解Hibernate如何处理线程之间共享的对象,并且每个线程都试图将它保存到数据库。

这是我的理论问题:

1)我有一个带有属性的Person对象(ssn,name,address)。 2)三个线程引用此person对象,每个线程调用savePersonToHibernate方法(...)

public void savePersonToHibernate(Person person)
{
...
session.saveOrUpdate(person)
...
}

Hibernate如何处理将同一对象写入存储的3个线程?它是否将所有事务放入队列中,因此当第一个线程创建行和标识符(设置id)时,剩下的两个线程只会更新它(在这种情况下)没有更改?或者我实际上是否有机会在数据库中有2行或3行,当前对象只引用最后创建的标识符?

我希望它有点意义......我正在建立一个队列系统,数据需要被引用到需要动态创建的类别......如果两个或多个线程得到一些数据这两个都需要创建相同的类别,我不想重复。

我希望这有道理......你会做什么?

1 个答案:

答案 0 :(得分:1)

我假设所有提到的线程都使用不同的会话,否则你会遇到麻烦,因为hibernate会话不是线程安全的。

只是为了说清楚,如果所有三个线程都使用相同的person实例,并且这是一个新对象,则您遇到麻烦,因为hibernate在访问或修改对象时不进行任何同步。基本上每个线程的工作方式就好像其他线程不存在一样,因此每个线程首先检查人是否具有非null id,如果id为null则尝试生成它,然后将其分配给适当的实体字段。根据不同线程中check-generate-assign的时间和可见性的影响,并发创建的结果是不可预测的。

让我们看看如果所有线程都使用不同的人物实例但具有相同的属性值会发生什么。在这种情况下,每个线程将尝试在数据库中创建三个不同的行,如果基础表上没有唯一约束(如唯一名称),它将成功。

您创建类别的特定方案实施起来并不是非常简单。我们的想法是尝试创建类别,但如果它已经存在则捕获异常。在后一种情况下,从数据库中读取现有类别并使用它。但请记住,条件插入的实现并不简单,可能依赖于RDBMS。对于PostgreSQLSQL Server的upsert操作,您可能会稍微复杂一些但相关的示例。