Java JPA保存验证错误
我有以下实体:Java JPA保存验证错误,java,spring,hibernate,relational-database,bean-validation,Java,Spring,Hibernate,Relational Database,Bean Validation,我有以下实体: 祖父 父亲 孩子 他们的关系是: 祖父-[hasMany]-父亲-[hasMany]-孩子 父亲在子字段上有@NotEmpty验证: 若并没有指定验证,它将工作并保存到DB,当父亲在添加到祖父之前被保存时,它也会工作。研究表明,在验证阶段,父对象的children属性为null(可能是因为children未保存且没有ID),但它设置了祖父属性 如何在不先保存子实体和父实体的情况下实现保存和验证 @Test public void contextLoads() { gr
- 祖父
- 父亲
- 孩子
@Test
public void contextLoads() {
grandFatherRepository.deleteAll();
GrandFather grandFather = (GrandFather)((grandFatherRepository.findAll().toArray().length == 0) ? null : grandFatherRepository.findAll().toArray()[0]);
if (grandFather == null) {
grandFather = grandFatherRepository.save(new GrandFather());
}
Father father = new Father();
grandFather.addFather(father);
Child child = new Child();
father.addChild(child);
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(grandFather);
System.out.print(constraintViolations); // prints null
grandFatherRepository.save(grandFather); // Crashes here
}
@Entity
public class GrandFather extends BaseEntity {
@OneToMany(mappedBy = "grandFather", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Father> fathers;
public GrandFather() {}
public Set<Father> getFathers() {
return fathers;
}
public void setFathers(Set<Father> fathers) {
this.fathers = fathers;
}
public void addFather(Father father) {
if (father == null) {
return;
}
if (fathers == null) {
fathers = new HashSet<>();
}
father.setGrandFather(this);
fathers.add(father);
}
}
@Entity
public class Father extends BaseEntity {
@NotEmpty
private String name;
@ManyToOne(cascade = CascadeType.DETACH)
private GrandFather grandFather;
@NotEmpty
@OneToMany(mappedBy = "father", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Child> children = new HashSet<>();
public Father() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public GrandFather getGrandFather() {
return grandFather;
}
public void setGrandFather(GrandFather grandFather) {
this.grandFather = grandFather;
}
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
public void addChild(Child child) {
if (child == null) {
return;
}
if (children == null) {
children = new HashSet<>();
}
child.setFather(this);
children.add(child);
}
}
@Entity
public class Child extends BaseEntity {
@ManyToOne(cascade = CascadeType.DETACH)
private Father father;
public Child() {
}
public Father getFather() {
return father;
}
public void setFather(Father father) {
this.father = father;
}
}
@测试
public void contextLoads(){
grandFatherRepository.deleteAll();
祖父祖父祖父=(祖父)((祖父祖父存储库.findAll().toArray().length==0)?null:祖父存储库.findAll().toArray()[0]);
if(祖父==null){
祖父=grandFatherRepository.save(新祖父());
}
父亲=新父亲();
祖父。父亲(父亲);
子项=新子项();
父亲,孩子;
Set constraintViolations=validator.validate(祖父);
System.out.print(constraintViolations);//打印空值
祖父存储库。保存(祖父);//在此崩溃
}
@实体
公共类实体{
@OneToMany(mappedBy=“祖父”,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
私人设定的父亲;
公共服务{}
公共集getFathers(){
回归父亲;
}
公共无效集合父对象(集合父对象){
这个。父亲=父亲;
}
父亲(父亲){
if(父==null){
返回;
}
如果(父亲==null){
父类=新HashSet();
}
父亲,祖父(这个);
父亲。添加(父亲);
}
}
@实体
公共类父实体{
@空空如也
私有字符串名称;
@多通(级联=级联类型.DETACH)
私人祖父;
@空空如也
@OneToMany(mappedBy=“父”,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
private Set children=new HashSet();
公父(){
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共祖父(祖父){
还祖父;
}
公共空间(外祖父){
这个。祖父=祖父;
}
公共集getChildren(){
返回儿童;
}
公共无效集合子对象(集合子对象){
这个。孩子=孩子;
}
公共无效添加子对象(子对象){
if(child==null){
返回;
}
if(children==null){
children=newhashset();
}
孩子。父亲(这个);
添加(child);
}
}
@实体
公共类子级扩展BaseEntity{
@多通(级联=级联类型.DETACH)
私人父亲;
公共儿童(){
}
公共父亲{
回归父亲;
}
父亲(父亲){
这个。父亲=父亲;
}
}
您能否同时显示其他实体的关系?我假设您在这里没有执行双向关系,但您正在非所有者侧添加对象。@Vaelyr更新了代码因为您使用的是双向关系,我相信您必须始终在祖父之前显式保存父亲,以防它已经存在。不管怎样,建议您始终这样做。您能否同时显示您的其他实体的关系?我假设您在这里没有执行双向关系,但您正在非所有者侧添加对象。@Vaelyr更新了代码因为您使用的是双向关系,我相信您必须始终在祖父之前显式保存父亲,以防它已经存在。无论如何,建议始终这样做。
ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=children, rootBeanClass=class com.example.models.Father, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'}
@Test
public void contextLoads() {
grandFatherRepository.deleteAll();
GrandFather grandFather = (GrandFather)((grandFatherRepository.findAll().toArray().length == 0) ? null : grandFatherRepository.findAll().toArray()[0]);
if (grandFather == null) {
grandFather = grandFatherRepository.save(new GrandFather());
}
Father father = new Father();
grandFather.addFather(father);
Child child = new Child();
father.addChild(child);
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(grandFather);
System.out.print(constraintViolations); // prints null
grandFatherRepository.save(grandFather); // Crashes here
}
@Entity
public class GrandFather extends BaseEntity {
@OneToMany(mappedBy = "grandFather", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Father> fathers;
public GrandFather() {}
public Set<Father> getFathers() {
return fathers;
}
public void setFathers(Set<Father> fathers) {
this.fathers = fathers;
}
public void addFather(Father father) {
if (father == null) {
return;
}
if (fathers == null) {
fathers = new HashSet<>();
}
father.setGrandFather(this);
fathers.add(father);
}
}
@Entity
public class Father extends BaseEntity {
@NotEmpty
private String name;
@ManyToOne(cascade = CascadeType.DETACH)
private GrandFather grandFather;
@NotEmpty
@OneToMany(mappedBy = "father", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Child> children = new HashSet<>();
public Father() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public GrandFather getGrandFather() {
return grandFather;
}
public void setGrandFather(GrandFather grandFather) {
this.grandFather = grandFather;
}
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
public void addChild(Child child) {
if (child == null) {
return;
}
if (children == null) {
children = new HashSet<>();
}
child.setFather(this);
children.add(child);
}
}
@Entity
public class Child extends BaseEntity {
@ManyToOne(cascade = CascadeType.DETACH)
private Father father;
public Child() {
}
public Father getFather() {
return father;
}
public void setFather(Father father) {
this.father = father;
}
}