gpt4 book ai didi

JPA 实体仅在方法完成后更新

转载 作者:行者123 更新时间:2023-12-02 05:41:45 25 4
gpt4 key购买 nike

我有一个异步注释方法,它通过方法参数接收实体。在这个方法中,我尝试设置一个变量三次:

@Inject EntityDao entityDao;

@Asynchronous
public Future<String> doSomething (MyEntity p_myEntity) {

MyEntity myEntity = entityDao.merge(p_myEntity); // change from detached to attached
// em.contains(myEntity) returns true

myEntity.setName("Joe 1"); // newer set in database
// A System.out.println(myEntity.getName()) does say "Joe 1"

try {
Thread.sleep(20*1000);
} catch () ...etc

myEntity.setName("Joe 2"); // newer set in database
// A System.out.println(myEntity.getName()) does say "Joe 2"

try {
Thread.sleep(20*1000);
} catch () ...etc

myEntity.setName("Joe 3"); // only one set in database

return new AsyncResult<>("done");
}

编辑:感谢 PedroKowalski,我对这个问题有了更好的理解,我将重新表述。

在执行上述方法期间,我有两种方法来检查 myEntity.setName() 是否实际更改:

  • 在 sleep() 期间,我检查数据库名称值是否发生更改
  • 网页上会显示 MyEntity 对象列表(带有名称),该列表每 2 秒更新一次。

上述两种方法都表明值“Joe 1”和“Joe 2”在数据库中较新。只有在 doSomething() 方法完成后,姓氏集 (Joe 3) 才会被放入数据库中。

所以我的问题是:为什么值“Joe 1”和“Joe 2”没有放入数据库中,而只有最后一个值放入数据库中?

最佳答案

如果您使用 JTA 事务,则事务边界从方法的开始延伸到其结束。

因此,在事务 T2 中看不到在事件事务 T1 中所做的更改。如果你仔细想想,这是非常合理的。假设 T2 可以对 T1 更改但未提交的数据进行操作。 T1 回滚后,对 T1 中的实体所做的所有更改都必须失效。您最终陷入了 T2 对无效数据进行操作的情况。

这就是为什么您不会从 T1 以外的任何事务中看到“Joe 1”(该值仅在 T1 中更改)。您只能在方法结束(T1 提交)时看到“Joe 2”。

EntityManager#flush()将数据与底层数据库同步,但不提交。有关更多详细信息,您可以查看此线程: http://www.java.net/node/665442#comment-678155

在这种情况下我可以看到三种解决方案:

  1. 乐观锁定可以避免两个事务 T1 和 T2 更改相同数据(相同实体)的情况。如果您没有锁定,则只有最后提交的事务更改才会反射(reflect)在数据库中(因此前一个事务所做的更改将丢失)。通过锁定,您将在最后提交的事务中收到异常,因此不会丢失数据。

  2. 悲观锁定可以在修改时锁定数据。在这种情况下,您的事务 T2 在 T1 完成之前不会对数据进行操作。

  3. 最后 - 最简单的情况是(如果可能的话)将您的方法分成更小的 block 。

HTH。

关于JPA 实体仅在方法完成后更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7890272/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com