繁体   English   中英

外键未存储在子实体中(一对多)

[英]Foreign key not stored in child entity (one-to-many)

我刚冬眠,就偶然发现了这个问题,我找不到解决方案。

当持久化父对象(与子对象具有一对多关系)时,该父对象的外键不存储在子对象的表中。

我的课程:

Parent.java

@javax.persistence.Table(name = "PARENT")
@Entity
public class PARENT {
  private Integer id;

  @javax.persistence.Column(name = "ID")
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  private Collection<Child> children;

  @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
  @Cascade({org.hibernate.annotations.CascadeType.ALL})
  public Collection<Child> getChildren() {
    return children;
  }

  public void setChildren(Collection<Child> children) {
    this.children = children;
  }
}

Child.java

@javax.persistence.Table(name = "CHILD")
@Entity
@IdClass(Child.ChildId.class)
public class Child {
  private String childId1;

  @Id
  public String getChildId1() {
    return childId1;
  }

  public void setChildId1(String childId1) {
    this.childId1 = childId1;
  }

  private String childId2;

  @Id
  public String getChildId2() {
    return childId2;
  }

  public void setChildId2(String childId2) {
    this.childId2 = childId2;
  }

  private Parent parent;

  @ManyToOne
  @javax.persistence.JoinColumn(name = "PARENT_ID", referencedColumnName = "ID")
  public Parent getParent() {
    return parent;
  }

  public void setParent(Operation parent) {
    this.parent = parent;
  }

  public static class ChildId implements Serializable {
    private String childId1;

    @javax.persistence.Column(name = "CHILD_ID1")
    public String getChildId1() {
      return childId1;
    }

    public void setChildId1(String childId1) {
      this.childId1 = childId1;
    }

    private String childId2;

    @javax.persistence.Column(name = "CHIILD_ID2")
    public String getChildId2() {
      return childId2;
    }

    public void setChildId2(String childId2) {
      this.childId2 = childId2;
    }

    public ChildId() {
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      ChildId that = (ChildId) o;

      if (childId1 != null ? !childId1.equals(that.childId1) : that.childId1 != null) 
        return false;
      if (childId2 != null ? !childId2.equals(that.childId2) : that.childId2 != null)
        return false;

      return true;
    }

    @Override
    public int hashCode() {
      int result = childId1 != null ? childId1.hashCode() : 0;  
      result = 31 * result + (childId2 != null ? childId2.hashCode() : 0);
      return result;
    }
  }
}

Test.java

public class Test() {

  private ParentDao parentDao;

  public void setParentDao(ParentDao parentDao) {
    this.parentDao = parentDao;
  }

  private ChildDao childDao;

  public void setChildDao(ChildDao childDao) {
    this.childDao = parentDao;
  }

  test1() {
    Parent parent = new Parent();

    Child child = new Child();
    child.setChildId1("a");
    child.setChildId2("b");
    ArrayList<Child> children = new ArrayList<Child>();
    children.add(child);

    parent.setChildren(children);
    parent.setValue("value");

    parentDao.save(parent); //calls hibernate's currentSession.saveOrUpdate(entity)
  }

  test2() {
    Parent parent = new Parent();
    parent.setValue("value");
    parentDao.save(parent); //calls hibernate's currentSession.saveOrUpdate(entity)

    Child child = new Child();
    child.setChildId1("a");
    child.setChildId2("b");
    child.setParent(parent);
    childDao.save(); //calls hibernate's currentSession.saveOrUpdate(entity)
  }
}

当调用test1()时 ,两个实体都被写入数据库,但是CHILD表中的字段PARENT_ID保持为空。

到目前为止,我唯一的解决方法是test2() -首先持久保留父级,然后持久化子级。

我的目标是通过对Parent的 save()的调用来保持父代及其子代。 有任何想法吗?

您还可以向父母添加其他方法,例如

public void addChild(Child child) 

做类似的事情

    child.setParent(this);

对于这种情况,我有一个好的解决方案:D

mappingBy表示inverse =“ true” 所以你必须反==“ false”

试试吧..

@OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.ALL})//javax.persistent.CascadeType
@JoinColumn(name = "parent_id")//parent's foreign key
public Collection<Child> getChildren() {
    return children;
}

我希望工作是一件好事

test1()中的主要问题是您没有在子对象中设置父对象。 你应该说.. child.setParent(parent)。 仅将孩子设置为父母并不意味着孩子知道父母。 实际上,它的孩子拥有关系。 因此,有必要在子对象中设置父对象。 父或子上的saveorUpdate()调用顺序不重要。

test2()之所以有效,是因为您已通过调用child.setParent()在子对象中设置了父对象。 这在test1()中丢失。

问题是,在test1()中,在保存父项之前先保存子项。 在test2()中,您首先要保存父级,然后是子级,这是正确的,这就是为什么它可以工作的原因。

这样想吧。 您可以在父亲和母亲出生之前出生吗? 不,它们必须存在才能存在。 像在test2()中一样,先创建父级,再创建子级。

如果需要,可以编辑parentDAO.save()以保存或更新任何引用的子代。 这样一来,他们节省1个电话。

在保存父项之前,尚未为其分配ID。 因此,当您首先保存孩子时,它没有要保存的外键。 您想要像test2()一样进行操作,但要包装在事务中。 在这里看看。 我认为标题为“使用EJB / CMT进行事务划分”的部分可能是您想要的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM