【问题标题】:How to make a transaction only persist objects that are referred inside the transaction method?如何使事务只保留事务方法内部引用的对象?
【发布时间】:2017-08-30 19:40:19
【问题描述】:

我的 Web 应用程序使用 Spring (4.2.9)、Spring Data (3.2.5)、JPA、Hibernate (4.3.8) 和 MS SQL Server (2014)。这是控制器方法中的流程:

ObjectA = service.getObjectAById(some_id);
o.setUpdate(new Date()); //for temporary need.
service.createObjectBAndSaveIt(new ObjectB());

这里有两个在服务层相关的方法:

@Override
@Transactional(readOnly = true)
public ObjectA getObjectAById(Long id) {
   //load ObjectA from database
}

@Override
public void createObjectBAndSaveIt(Long id) {
  //create and save ObjectB
}

请注意,ObjectA 和 ObjectB 没有直接或间接的关系。 ObjectA 有一个版本字段如下:

@Version
private Long version = 1L;

请注意,当执行上述 Web 流程时,ObjectA 的版本号会增加 1,即使 service.createObjectBAndSaveIt 中没有引用或使用它。据我所知,Hibernate 在执行service.createObjectBAndSaveIt 时会进行脏检查并保存 OjbectA。我不想要这种默认行为。如何使系统仅保留出现在事务处理方法中的对象(例如 ObjectB)?任何指针或示例将不胜感激。

【问题讨论】:

  • 如果您更新/创建对象 B 使用来自对象 A 的数据,则此行为正是您所需要的,否则您可能会读取 skew。
  • @GionJh,感谢您的参与!如代码所示,创建和保存 ObjectB 完全独立于 ObjectA。 “读取偏差”是什么意思?
  • 这是并发事务写入和读取相同数据的副作用,您可以通过乐观锁定来避免它。谷歌它。
  • 如果他们是独立的你不需要它..我只能说弹簧数据是这里的玩家..但不深入了解它我无法进一步帮助你
  • GionJh,感谢您的参与。问候。

标签: hibernate spring-mvc jpa


【解决方案1】:

Spring 使用默认情况下所需的事务传播。尝试使用 @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 显式注释您的方法,以处理您想要持久化的数据(在本例中为对象 B),并为非写入数据(在本例中为对象 A)使用 @Transactional(readOnly = true)

Spring 文档指出:

默认@Transactional设置如下:

传播设置为 PROPAGATION_REQUIRED。隔离级别为 ISOLATION_DEFAULT。事务是读/写的。

【讨论】:

  • @guihebl,感谢您提供的信息!我会对此进行调查并进行测试,然后再报告。再次感谢!
  • 嗨@guilhbel,我看了这个,但我不确定 Propagation.REQUIRES_NEW 如何提供帮助。基本上,ObjectA 已经通过readOnly = true 加载。它仅在 Web 控制器的流程中使用。它是在流程中临时修改的,我不想坚持这样的改变。但是,创建和保存 ObjectB 会使对 ObjectA 的更改持续存在,这不是我想要的。我希望“service.createObjectBAndSaveIt”只保留新的 ObjectB 实例。
  • @curious1 你是在使用 JPA 还是在 objectA 和 objectB 之间的关系上注释了 CascadeType.ALL ?也许这可能导致 ObjectA 的自动合并,如果您使用 JPA,请尝试从持久化上下文中分离对象 A,在持久化 objectB 之前调用 void detach(java.lang.Object entity)
  • 感谢您对我的跟进!如原始帖子中所述,ObjectA 和 ObjectB 之间没有直接或间接的关系(引用)。 ObjectA 永远不会传递给service.createObjectBAndSaveIt 或在service.createObjectBAndSaveIt 中使用。我不希望由于此方法的 inovke 而对 Web 流中和 service.createObjectBAndSaveIt 之外修改的其他对象的更改保持不变。我不确定这种自动持久化是否是 JPA/Hibernate 的默认行为。如果是的话,我希望改变它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-06
  • 1970-01-01
相关资源
最近更新 更多