我正在使用GlassFish 4.1,EclipseLink和Derby开发Java EE应用程序,并且今天注意到当我创建一个新的Person实体时,新创建的实体的版本是2而不是1.以下是我的Person Entity。
@Entity
public class Person {
@Id
private Long id;
@Version
private Integer version;
private String name;
@OneToOne
private Portrait portrait;
@OneToMany(mappedBy = "person")
private List<Portrait> portraits;
...
}
以下是我的肖像实体。
@Entity
public class Portrait {
@Id
private Long id;
@Version
private Integer version;
private String name;
@ManyToOne
private Person person;
...
}
以下是我的无状态EJB createPerson方法的一部分,该方法导致新创建的Person实体的版本为2.
Person person = new Person();
person.setName("Fred Smith");
em.persist(person);
Portrait portrait = new Portrait();
portrait.setName("Fred Smith Portrait");
portrait.setPerson(person);
portrait = portraitManager.createPortrait(portrait); //portraitManager is another stateless EJB.
person.setPortrait(portrait); // Commenting out this line results in newly created Person entity with a version of 1.
person.getPortraits().add(portrait);
如果我注释掉上面的person.setPortrait(portrait)
行,则使用版本1创建Person实体。
我在其他帖子中读到,如果字段更改或拥有的关系发生更改,JPA将增加实体的版本。方法从createPortrait方法返回后,我正在更改拥有的关系,但我仍然在同一个事务中,所以不明白为什么JPA需要增加版本。
为什么JPA会在同一个事务中两次增加Person实体的版本?
根据评论中的要求,我打开了EclipseLink日志记录,并在正常流程中观察到以下内容:
如果我评论出“person.setPortrait(Portrait);”命令,日志显示以下内容:
为了更具体地说明我的问题,为什么EclipseLink会更新正常流程的第7步中的版本? EclipseLink在步骤2中创建了版本1的行,并且没有其他事务更新该行,因为该行只存在于此事务中,直到提交为止。
我怀疑答案是这只是EclipseLink选择在这种情况下工作的方式。