java怎么实现级联展示父亲,将子实体持久化操作级联到其父实体

I have a OneToMany association with two entities that I have set up using Hibernate annotations. The Child entity of this association has a composite primary key that consists of the foreign key parent column and another identifier childName. This seems to cause a "Referential integrity constraint violation" when I attempt to cascade a commit to the parent by saving the child entity.

I have created a simple working example of the issue that abstracts away from the actual scenario that I am modelling with this relationship, but it means that I know the problem is due to this association and using a composite primary key.

Why can I not commit both entities by saving the child entity? Why does it violate foreign key constraints?

Main test method*:

// Create some detached entities

Parent p = new Parent();

p.setName("Fooson");

// New child id

Child.ChildPK pk = new Child.ChildPK();

pk.setParentName(p);

pk.setChildName("Barty");

// Set id to new Child

Child c = new Child();

c.setChildPK(pk);

// Add child to parent

p.getChildren().add(c);

// Saving the parent

// service.parentDao.save(p); // if this is uncommented, it works fine

// Cascade child and associated parents in one transaction

service.childDao.save(c); // ConstraintViolationException

Child.java

@Entity

@Table(name="Child")

public class Child implements Serializable {

@EmbeddedId

private ChildPK id;

public ChildPK getChildPK() {

return id;

}

public void setChildPK(ChildPK childPK) {

this.id = childPK;

}

@Embeddable

public static class ChildPK implements Serializable

{

@ManyToOne(cascade=CascadeType.ALL)

@JoinColumn(name="name")

Parent parent;

@Column(name="childName")

String childName;

public Parent getParentName() {

return parent;

}

public void setParentName(Parent parentName) {

this.parent = parentName;

}

public String getChildName() {

return childName;

}

public void setChildName(String childName) {

this.childName = childName;

}

@Override

public int hashCode() {

int hash = 5;

hash = 67 * hash + Objects.hashCode(this.parent);

hash = 67 * hash + Objects.hashCode(this.childName);

return hash;

}

@Override

public boolean equals(Object obj) {

if (obj == null) {

return false;

}

if (getClass() != obj.getClass()) {

return false;

}

final ChildPK other = (ChildPK) obj;

if (!Objects.equals(this.parent, other.parent)) {

return false;

}

return Objects.equals(this.childName, other.childName);

}

@Override

public String toString() {

return "ChildPK{" + "parentName=" + parent.getName() + ", childName=" + childName + '}';

}

}

@Override

public String toString() {

return "Child{" + "id=" + id + '}';

}

}

Parent.java

@Entity

@Table(name="Parent")

public class Parent implements Serializable {

@Id

@Column(name="name")

private String name;

@OneToMany(mappedBy="id.parentName", cascade=CascadeType.ALL)

Set children = new HashSet<>(0);

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Set getChildren() {

return children;

}

public void setChildren(Set children) {

this.children = children;

}

@Override

public int hashCode() {

int hash = 3;

hash = 73 * hash + Objects.hashCode(this.name);

return hash;

}

@Override

public boolean equals(Object obj) {

if (obj == null) {

return false;

}

if (getClass() != obj.getClass()) {

return false;

}

final Parent other = (Parent) obj;

if (!Objects.equals(this.name, other.name)) {

return false;

}

return true;

}

@Override

public String toString() {

return "Parent{" + "name=" + name + ", children=" + children + '}';

}

}

The complete exception message is:

Exception in thread "main" org.hibernate.exception.ConstraintViolationException:

Could not execute JDBC batch update

...

Caused by: org.h2.jdbc.JdbcBatchUpdateException:

Referential integrity constraint violation:

"FK3E104FCBA07683D: PUBLIC.CHILD FOREIGN KEY(NAME) REFERENCES

PUBLIC.PARENT(NAME) ('Fooson')"; SQL statement:

insert into Child (childName, name) values (?, ?)

...

* the main method refers to DAO and ServiceLayer objects that I have not shown here because I don't think it is relevant to the problem. I can, however, post these if asked for.

解决方案

It doesn't make sense to cascade a save operation from a Child to a Parent entity, it's the other way around.

That's because the operations will be:

save the Child

propagate the save operation to Parent

but the Child depends on the Parent.id for setting its FK.

You need to visualize this operation flow from the database perspective too. Can you save a Child who references a non-existing Parent? Of course, not.

Think what will happen when you delete a Child entity. The cascade will propagate to the Parent and then to all its Children.

So, you have to remove the cascading from the Embeddable class:

@ManyToOne(cascade=CascadeType.ALL)

and uncomment the code that works fine:

// Saving the parent

service.parentDao.save(p); // if this is uncommented, it works fine

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值