Java JPA中的并发(过时数据)问题

Java JPA中的并发(过时数据)问题,java,orm,jpa,Java,Orm,Jpa,假设我有以下签名的方法 Object getData(int id) { //create a entity manager //get data frm db //return data } updateData() { Object obj = getData(id) //get entity manager //start transcation tx //update //commit tx } 现在它会导致并发问题吗?在最坏的情况下数据会过时吗

假设我有以下签名的方法

Object getData(int id) {  
  //create a entity manager
  //get data frm db
  //return data
}

updateData() {
  Object obj = getData(id) 
  //get entity manager
  //start transcation tx
  //update
  //commit tx
}
现在它会导致并发问题吗?在最坏的情况下数据会过时吗?例如。 如果我
getData
并且在我更新时,如果有人更新了数据,我的
updateData
会有过时的数据吗? 现在我可以使用以下命令:我能解决问题吗

Object getData(int id,Entitymanager em) {  

      //get data frm db using em
      //return data
    }

 updateData() {
      Object obj = getData(id) 
      //get entity manager em
      //start transcation tx
      //getdata using getData(id,em)
      //commit tx
    }
是的,那是可能发生的

如果您得到一个实体(版本1),其他人修改它(创建版本2),然后您修改版本1并保存它,版本2中的任何更改都将丢失


要阻止这种情况发生,请通过向实体添加@Version属性来使用乐观并发。如果在get和update之间发生提交,将引发异常。此时,您可以选择最佳选项来处理它。

多线程环境中也可能存在问题,如果多个用户同时访问同一段代码,它可以创建锁,为此,您可以使用行级锁技术,这将对您有所帮助。查看下面的链接


如果两个单独的请求同时访问
updateData()
,您可能会得到过时的数据。您可以通过在
updateData()
中锁定获取的数据来处理过时。如果使用Hibernate作为JPA提供程序,则可以按如下方式锁定数据:

updateData() {
    Object obj = getData(id);
    Session session = (Session) em.getDelegate();
    session.refresh(obj, LockMode.UPGRADE);
}
刷新是必要的,因为在获取数据和锁定数据之间,另一个事务可能会在
updateData
中完成


请记住,在
getData
updateData
中使用的实体管理器必须是相同的。

行级锁定在这里没有帮助:他将所有数据拉到事务之外。在同一事务内获取数据和更新数据会解决问题吗?请参阅我对原始post的新编辑获取数据事务内部意味着,在行锁定的情况下,并发更新将被迫等待第一次更新完成。但是,这两种方法都将继续运行,因此您的事务块需要注意,它不会覆盖另一个事务所做的任何事情。我仍然无法理解,使用原始帖子中的第二种方法是否可以处理该问题?如果现在我该如何解决?如果我需要锁定行,我该如何处理?@akp:我同意您的观点,行级锁定在这里没有帮助,相反,你可以使用同步技术吗?我不太确定这一点,因为在我没有使用它的情况下,但这可以帮助你,因为在同步期间,同步管理器将在会话中更新该实体的所有引用,如果其他人也在使用它。这个过程有点昂贵,但可以帮助您。