JPA实体仅在方法完成后更新
我有一个异步带注释的方法,它通过method参数接收一个实体。在此方法中,我尝试设置变量三次:JPA实体仅在方法完成后更新,jpa,asynchronous,merge,entity,Jpa,Asynchronous,Merge,Entity,我有一个异步带注释的方法,它通过method参数接收一个实体。在此方法中,我尝试设置变量三次: @Inject EntityDao entityDao; @Asynchronous public Future<String> doSomething (MyEntity p_myEntity) { MyEntity myEntity = entityDao.merge(p_myEntity); // change from detached to attached
@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");
}
@injectentitydao EntityDao;
@异步的
公共未来剂量(MyEntity p_MyEntity){
MyEntity MyEntity=entityDao.merge(p_MyEntity);//从分离更改为附加
//em.contains(myEntity)返回true
myEntity.setName(“Joe 1”);//数据库中较新的集合
//System.out.println(myEntity.getName())会说“Joe1”
试一试{
线程。睡眠(20*1000);
}捕获()…等
myEntity.setName(“Joe 2”);//数据库中较新的集合
//System.out.println(myEntity.getName())会说“Joe2”
试一试{
线程。睡眠(20*1000);
}捕获()…等
myEntity.setName(“Joe 3”);//数据库中只有一个集合
返回新的异步结果(“完成”);
}
编辑:多亏了佩德罗科瓦尔斯基,我对这个问题有了更好的理解,我将重新制定
在执行上述方法的过程中,我有两种方法来检查myEntity.setName()是否实际更改:
- 在sleep()期间,如果名称值发生更改,我将检查数据库
- 在网页上显示MyEntity对象列表(带有名称),该列表每2秒更新一次
因此,我的问题是:为什么值“Joe 1”和“Joe 2”没有放在数据库中,而只有最后一个值放在数据库中?如果使用JTA事务,则事务边界会从方法的开始扩展到结束 因此,在事务T2中看不到在活动事务T1中所做的更改。如果你仔细想想,这是很合理的。 假设T2可以对T1更改但未提交的数据进行操作。在T1回滚时,对T1中的实体所做的每个更改都必须无效。您已经在T2操作无效数据的情况下结束 这就是为什么您不会从T1以外的任何事务中看到“Joe1”(该值仅在T1中更改)。只有在方法结束(T1提交)时才能看到“Joe2” 将数据与基础数据库同步,但不会提交数据。有关更多详细信息,请参见以下线程: 在这种情况下,我可以看到三种解决方案:
- em.flush()期间,数据写入数据库。提交事务时,数据对其他用户/持久性上下文可见
- 您不会通过em.flush()手动刷新数据库,因此在提交事务时会自动调用em.flush()
- 事务在方法末尾提交,因此在刷新发生时提交,这意味着“Joe3”被写入数据库并提交