【问题标题】:Hibernate SaveOrUpdate - multiple workthreadsHibernate SaveOrUpdate - 多个工作线程
【发布时间】:2013-10-23 21:25:34
【问题描述】:

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

这是我的理论问题:

1) 我有一个带有属性(ssn、姓名、地址)的 Person 对象。 2)三个线程都引用了这个person对象,每个线程调用savePersonToHibernate(...)方法

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

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

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

我希望这是有道理的......你会怎么做?

【问题讨论】:

    标签: java database hibernate


    【解决方案1】:

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

    为了清楚起见,如果所有三个线程都使用同一个 person 实例并且这是一个新对象,那么你就有麻烦了,因为 hibernate 在访问或修改对象时不会进行任何同步。基本上每个线程都像其他线程不存在一样工作,因此每个线程都会首先检查人员是否具有非空 id,如果 id 为空,则尝试生成它,然后将其分配给适当的实体字段。取决于不同线程中 check-generate-assign 的时间安排以及并发创建的更改结果的可见性影响是不可预测的。

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

    您创建类别的特定场景不是很容易实现。这个想法是尝试创建类别但如果它已经存在则捕获异常。在后一种情况下,从数据库中读取现有类别并使用它。但请记住,条件插入的实现并非微不足道,并且可能依赖于 RDBMS。对于 PostgreSQLSQL Server 的 upsert 操作,您可以使用稍微复杂但相关的示例。

    【讨论】:

    • 感谢您的回答。由于这一步很关键,我决定创建一个“pre-category-queue”,它使用一个线程创建一个类别并将其放入映射中,将类别对象引用到主对象,然后将其放入真正的队列中,被多个线程拾取。它工作得很好,但它并不完全是在本书之后,但您通常可以避免对数据库的访问。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多