java - 与共享 id 的一对一关系要求子级了解父级

标签 java jpa spring-data

我在使用 Spring 数据将下面提供的实体存储到数据库时遇到问题。这两者之间使用 OneToOne 关系。仅当将parentObject 显式设置为childObject 时,它才起作用。这不是一个很好的解决方案,因为我希望子对象根本没有父对象。可能还是不可能? 非常相关的问题已发布here

@Entity
@Table(name = "parent_object")
public class ParentObject {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Long id;

@Column(name = "age")
private Long age;

@OneToOne(cascade = CascadeType.ALL, mappedBy = "parentObject")
private ChildObject childObject;

public ParentObject() {
}

public ParentObject(Long age, ChildObject childObject) {
    this.age = age;
    this.childObject = childObject;
}

public Long getId() {
    return id;
}

public Long getAge() {
    return age;
}

public ChildObject getChildObject() {
    return childObject;
}

public void setChildObject(ChildObject childObject) {
    this.childObject = childObject;
}
}

@Entity
@Table(name = "child_object")
public class ChildObject {
@Id
@Column(name = "child_id", unique = true, nullable = false)
private Long id;

@MapsId
@OneToOne
@JoinColumn(name = "child_id")
private ParentObject parentObject;

@Column(name = "name")
private String name;

public ChildObject() {
}

public ChildObject(String name) {
    this.name = name;
}

public Long getId() {
    return id;
}

public ParentObject getParentObject() {
    return parentObject;
}

public String getName() {
    return name;
}

public void setParentObject(ParentObject parentObject) {
    this.parentObject = parentObject;
}
}

但是,我真的不喜欢将parentObject设置为ChildObject:

ChildObject childObject = new ChildObject("name");
ParentObject parentObject = new ParentObject(12L, childObject);
childObject.setParentObject(parentObject);

这是共享 id 的唯一方法吗?如果没有明确设置parentObject,则会抛出以下错误:

Caused by: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [test.ChildObject.parentObject]
    at org.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:83) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:101) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]

最佳答案

您可以轻松封装操作,以便不需要有问题的调用:实际上,您应该始终这样做,以便内存中模型始终处于一致的状态:

public class ParentObject{

    public ParentObject(Long age, ChildObject childObject) {
        this.age = age;
        this.childObject = childObject;

        childObject.setParentObject(this);
    }

    public void setChildObject(ChildObject childObject) {
        this.childObject = childObject;
        childObject.setParentObject(this);
    }
}

现在,域模型 API 的客户端不需要了解有关从子到父的反向引用形式的任何信息。

ChildObject childObject = new ChildObject("name");
ParentObject parentObject = new ParentObject(12L, childObject); //all relationships now set correctly

关于java - 与共享 id 的一对一关系要求子级了解父级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43391714/

相关文章:

java - 分布式系统设计问题 - Scala

java - 具有不同返回值的一种方法的重构模式

java - Hibernate (Spring JPA) 子实体删除

java - 如何在后端线程中使用 JpaRepository?

spring - 如何在 Spring MongoDB 中将 2 个整数值连接成一个字符串

java - hibernate 映射 : referencing a set of Entities with OneToMany and one Entity of that set with OneToOne

java - 我如何减少 SQLite 表的 int 列

database - hibernate :OnDelete 与 cascade=CascadeType.REMOVE

java - 如何在hibernate中映射java属性

java - java中为什么有这么多日期和时间处理函数