【问题标题】:Hibernate thread-safe collectionsHibernate 线程安全集合
【发布时间】:2013-12-10 21:03:03
【问题描述】:

这在某种程度上是Hibernate session thread safety 的延续。所有细节也适用于此。简而言之,执行遵循以下模式:

1. Read entity
2. Do expensive, easily parallelizable work
3. Persist changes

实体都配置为预加载,2期间根本不访问会话。

2 中涉及的工作需要不经常修改持久性集合。这就是我现在拥有的:

synchronized (parentEntity) {
    parentEntity.getChildEntities().add(childEntity);
}

这工作得很好,但我正在尝试“防止白痴”这个系统,并且我正在寻找一种方法将并发控制尽可能向下移动到持久层中。我已经在 dao 中尝试过:

@Transactional
public ParentEntity getParentEntityById(long id) {
    ParentEntity parent = ...;
    parent.setChildren(Collections.synchronizedSet(parent.getChildren()));
    return parent;
}

导致org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance...

有没有人可以在休眠集合中引入线程安全性,或者其他一些干净的方法来控制并发访问和修改,而无需污染业务逻辑?

更新- 根据佩斯的建议,这是我最终要做的:

@Transactional
public ParentEntity getParentEntityById(long id) {
    ParentEntity parent = ...;
    currentSession().evict(parent);
    parent.setChildren(Collections.synchronizedSet(parent.getChildren()));
    return parent;
}

工作完成后,我把所有的孩子都救了出来,然后打电话给currentSession().merge(parent)。像魅力一样工作!

【问题讨论】:

    标签: java multithreading hibernate collections


    【解决方案1】:
    1. 读取实体
    2. 分离实体
    3. 做昂贵的、易于并行化的工作
    4. 合并实体
    5. 提交事务

    如果第 3 步需要花费大量时间,那么我建议您:

    1. 打开一个会话(可以是只读的)
    2. 读取实体
    3. 关闭会话
    4. 做昂贵的、易于并行化的工作
    5. 打开一个新会话
    6. 合并实体
    7. 关闭会话

    在分离/未附加时,您应该能够将集合包装在线程安全集合中。合并不应该关心您拥有什么集合实现。不过我还没有测试过。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      • 2011-12-15
      • 2013-07-06
      • 1970-01-01
      • 1970-01-01
      • 2011-05-29
      • 2012-05-27
      相关资源
      最近更新 更多