【问题标题】:OneToOne relation with shared id requires child to know about parent与共享 ID 的 OneToOne 关系要求孩子了解父母
【发布时间】:2017-04-13 11:58:02
【问题描述】:

我在使用 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]

【问题讨论】:

  • 我已经从 ChildObject 类中删除了 parentObject 字段,将 @JoinColumn(name = "child_id") private ChildObject childObject 添加到 parentObject 并删除了 mappedBy。我可能错过了一些东西,因为在给出建议之后引发了以下错误:原因:org.hibernate.id.IdentifierGenerationException:必须在调用 save() 之前手动分配此类的 ID:

标签: java jpa spring-data


【解决方案1】:

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

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 的客户端不需要知道任何关于从 Child 到 Parent 的反向引用表单。

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

【讨论】:

    【解决方案2】:

    由于您有双向关系(两边都有 OneToOne 注释),您需要在另一边保存关系每一侧的引用,如果您不喜欢这样,您可以通过以下方式将关系转换为单向关系从一侧删除引用和映射。

    【讨论】:

    • 好的,目的是获得工作单向关系。在子类@Id @Column(name = "child_id", unique = true, nullable = false) private Long id;在父类中:@OneToOne(orphanRemoval = true, cascade = CascadeType.ALL) @JoinColumn(name = "child_id") private ChildObject childObject;但是错误是由以下原因引起的:org.hibernate.id.IdentifierGenerationException:必须在调用 save() 之前手动分配此类的 ids
    • 如果关系是单向的,你不应该在关系的每一边都有引用,例如,要使从 ParentObject 到 ChildObject 的关系是单向的,你需要删除 ChildObject 中的 ParentObject 引用
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多