java - Hibernate 线程安全集合

标签 java multithreading hibernate collections

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

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

实体都配置为eager loading,2期间根本不访问session。

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:具有 cascade="all-delete-orphan"的集合不再被拥有实体实例引用...

有没有人有办法为 hibernate 集合引入线程安全,或者有其他干净的方法以不需要污染业务逻辑的方式来控制并发访问和修改?

更新- 根据 Pace 的建议,这是我最终做的事情:

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

工作完成后,我保存所有子项并调用 currentSession().merge(parent)。就像一个魅力!

最佳答案

  1. 阅读实体
  2. 分离实体
  3. 做昂贵的、容易并行化的工作
  4. 合并实体
  5. 提交交易

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

  1. 打开一个 session (可以是只读的)
  2. 阅读实体
  3. 结束 session
  4. 做昂贵的、容易并行化的工作
  5. 打开一个新 session
  6. 合并实体
  7. 结束 session

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

关于java - Hibernate 线程安全集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20204897/

相关文章:

java - 什么时候消息传递(例如 JMS)是多线程的替代方案?

java - Hibernate Bean 验证在类路径中不可用

java - 具有通用服务的 Spring Boot 映射器

java - 设置 org.eclipse.swt.widgets.Spinner 的小数点分隔符

c++任意线程数, fatal error

multithreading - 替换为Thread.Suspend-恢复而不影响性能

hibernate - 由 : javax. validation.ConstraintViolationException 引起:类验证失败

java - JdbcTemplate 抛出 java.sql.SQLException :

java - 在 netbeans 中使用 JSlider 缩放 jPanel

java - 桌面应用程序如何与 Web 应用程序通信?