Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java @即使从未调用persist,版本列也会更新_Java_Database_Jpa_Persistence_Jpa 2.0 - Fatal编程技术网

Java @即使从未调用persist,版本列也会更新

Java @即使从未调用persist,版本列也会更新,java,database,jpa,persistence,jpa-2.0,Java,Database,Jpa,Persistence,Jpa 2.0,我有一个包含两个表的数据库(更确切地说,但在本例中这并不重要)。其中一个具有对另一个的外键引用。这些可能是映射: @Entity @Table public class A { @Id public String id; @Version public int version; @OneToMany(targetEntity = B.class, mappedBy = "a", cascade = CascadeType.

我有一个包含两个表的数据库(更确切地说,但在本例中这并不重要)。其中一个具有对另一个的外键引用。这些可能是映射:

@Entity @Table public class A {
   @Id public String id;
   @Version public int version;
   @OneToMany(targetEntity = B.class,
              mappedBy = "a",
              cascade = CascadeType.ALL,
              fetch = FetchType.LAZY)
   public Collection<B> bs;

   ...
}

@Entity @Table public class B {
   @Id public String id;
   @Version public int version;
   @ManyToOne(targetEntity = A.class,
              cascade = CascadeType.ALL,
              fetch = FetchType.LAZY)
   public A a;

   ...
}
这非常有效:新数据可以持久化,而现有数据不能持久化

然而!无论for each循环中发生什么,我的数据库中的version列始终会更新。我获取了一组样本数据,将其保存在空表中(版本为0);我已经获取了相同的样本数据集并再次将其持久化(
EntityManager.persist(Object)
从未被调用),并且版本字段(在
A
中)得到了更新,但我无法想象为什么

我知道这样一个事实,即使
EntityManager.persist(Object)
从未被调用,我的持久性提供程序(Hibernate)也会生成更新语句来增加版本列

问题:为什么?我怎样才能防止这种情况?为了避免这种情况,我应该改变我的数据持久化方法吗?谢谢

 B b = em.find(B.class, c.getBId()); // a `B` generally doesn't exist in      
 if (null == a) {  
我想您在发布这两行代码时犯了一个小错误,if条件中的变量应该是b而不是a。如果是这种情况,则第行会导致版本字段的更新

 a.bs.add(b); 
我想您在发布这两行代码时犯了一个小错误,if条件中的变量应该是b而不是a。如果是这种情况,则第行会导致版本字段的更新

 a.bs.add(b); 

我认为这里发生的事情是,你设置了乐观的力量增量。如果将其设置为纯乐观,则不会看到更新。javadoc对这种行为的解释是精确的,但相当密集;还有一种可能会有所帮助的方法

我认为乐观的力量增量的意义在于它保护了数据库的一致性。假设有两个As,a1和a2,每个都有一个B。两个线程同时加载它们。线程1将a1设置为有两个B,将a2设置为有一个B(现状)。螺纹2将a1设置为一个B(现状),将a2设置为两个B。线程1在线程2之前提交。使用乐观的_FORCE_增量,线程2将得到一个异常,因为对象已被线程1修改。使用OPTIMIZE,线程2会成功,因为每个线程只会在它添加B的对象上碰撞版本。如果线程2成功,数据库现在表示一种状态,即提交的线程a1和a2都没有两个B

现在,这种不一致性——一种隐含的状态合并——可能是可以接受的,而且确实是您想要的。但JPA不能假设,总的来说,如此乐观的力量增量是可用的。我不知道这是默认设置(我找不到任何文档这样说,但这是合理的),或者您是否在其他地方明确设置它


至于解决方案,如果根本没有修改任何内容,您就不能提交会话。如果您正在处理某些对象被修改而某些对象未被修改的情况,则可以在其自己的会话中处理每个对象。或者您可以使用乐观锁定。如果我是对的,那就是

我认为这里发生的事情是,你设置了乐观的力量增量。如果将其设置为纯乐观,则不会看到更新。javadoc对这种行为的解释是精确的,但相当密集;还有一种可能会有所帮助的方法

我认为乐观的力量增量的意义在于它保护了数据库的一致性。假设有两个As,a1和a2,每个都有一个B。两个线程同时加载它们。线程1将a1设置为有两个B,将a2设置为有一个B(现状)。螺纹2将a1设置为一个B(现状),将a2设置为两个B。线程1在线程2之前提交。使用乐观的_FORCE_增量,线程2将得到一个异常,因为对象已被线程1修改。使用OPTIMIZE,线程2会成功,因为每个线程只会在它添加B的对象上碰撞版本。如果线程2成功,数据库现在表示一种状态,即提交的线程a1和a2都没有两个B

现在,这种不一致性——一种隐含的状态合并——可能是可以接受的,而且确实是您想要的。但JPA不能假设,总的来说,如此乐观的力量增量是可用的。我不知道这是默认设置(我找不到任何文档这样说,但这是合理的),或者您是否在其他地方明确设置它


至于解决方案,如果根本没有修改任何内容,您就不能提交会话。如果您正在处理某些对象被修改而某些对象未被修改的情况,则可以在其自己的会话中处理每个对象。或者您可以使用乐观锁定。如果我是对的,那就是

实际上,
null==a
null==b
,谢谢。但是,如果在持久性上下文中找到
b
,那么
a.bs.add(b)
永远不会执行,因此与
a
相对应的版本字段不应该更新(至少在我的书中是这样)。好吧,找到b时你是对的,a没有更新。。但是,如果找不到b,则会创建一个新的b实体,并将其与找到的a关联。没错,但问题是,无论发生什么情况,我的数据库中的版本列始终会得到更新,即使找到了
b
,并且从未调用
EntityManager.persist(Object)
。我想知道为什么会发生这种情况,我能做些什么。事实上,
null==a
null==b
,谢谢。但是,如果在持久性上下文中找到
b
,那么
a.bs.add(b)
永远不会执行,因此与
a
相对应的版本字段不应该更新(至少在我的书中是这样)。好吧,找到b时你是对的,a没有更新。。但是当b找不到的时候