我在使用CascadeType.Persist进行JPA / Standalone项目时出现问题。我有一个Parent实体,它有一个Child实体列表,应该与Parent一起持久化,Parent的主键是使用Table(GeneratorType.TABLE)生成的,我用一个表来生成主键。
在家长中我有:
@OneToMany(mappedBy="parent",fetch=FetchType.EAGER,cascade= {CascadeType.PERSIST,CascadeType.DETACH})
List<Child> children;
//Getter and Setter
@PostPersist
public void setParentID(){
System.out.println("Inside Postpersist");
for(Child ch : this.children){
ch.setParent(this);
System.out.println(ch.getParent().getParentId());
}
}
在孩子:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "Parent_ID")
private Parent parent;
在DB中,我有一个非null设置为Parent表的Parent_ID列。当我持有一个Parent实体并且它已经设置了Child实体列表时,它会抛出一个
ConstraintViolationException: Cannot insert the value NULL into column 'Parent_ID', table 'jpaTest.Child', column does not allow nulls.
因为Parent对于所有Child实体都为null,尽管它将ParentId集打印到使用@PostPersist注释的方法中的每个Child实体
但是,当我将主键生成策略从TABLE类型更改为AUTO时,不会发生父和子的持久性。这是怎么回事以及为什么会这样。
提供者是Hibernate。我的数据库服务器是mssql。
答案 0 :(得分:2)
这种方法看起来有点弱,因为规范不会过多地支持修改生命周期回调中的其他实体:
通常,便携式应用程序的生命周期方法不应该 调用EntityManager或Query操作,访问其他实体 实例,或修改同一持久性内的关系 上下文。
此外,您无法保证在父级中子级和 @PostPersist 的级联顺序:
关于回调方法是否依赖于实现 在生命周期事件级联之前或之后调用 相关实体。应用程序不应该依赖于此顺序。
答案 1 :(得分:2)
是的,它没有省略级联持久性。我所要做的就是将Parent对象设置为Child,同时将Child实体添加到Parent中的子项列表中,因为它是双向关系。
在家长中:
public void setParentToChild(Child ch){
if(this.getChildren()==null){
this.children = new ArrayList<Children>();
}
this.children.add(cb);
//this is what worked. Also set the Parent to Child
cb.setCustomer(this);
}
现在在创建新的Parent和Child时,我调用此方法将child添加到parent。而JPA在业务代码中没有任何设置。谢谢你们。
答案 2 :(得分:1)
我的猜测是,孩子的父字段必须在持久化之前初始化,而不是在@PostPersist方法之后,可能在级联完成后调用。