繁体   English   中英

映射一对多休眠实体

[英]Mapping a bidirectional One-to-Many Hibernate Entity

我正在尝试在Hibernate中映射双向(一对多和多对一)关系。 尝试保存结果时出现错误。

我们得到的错误是:

由以下原因引起:org.hibernate.PropertyValueException:not-null属性引用了null或瞬态值:org.hibernate.engine.internal.Nullability.checkNullability(Nullability.java:92)处的com.example.Component.resultId

从下面的源代码中,一个Result可以具有多个Component并且许多Component可以属于一个Result 要求之一是Result中的resultId 必须String 此要求超出了我们的控制范围。

下面是一个示例实体源代码:

@Entity
@Table(name = "result")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Result extends AbstractEntity {

    @OneToMany(cascade = CascadeType.MERGE)
    @JoinColumn(name = "resultId")
    private List<Component> component = new ArrayList<>();
}

@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
    @ManyToOne(targetEntity = Result.class)
    private String resultId;
}

这是对我有用的解决方案

@Entity
@Table(name = "result")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Result extends AbstractEntity {

    @OneToMany(cascade = CascadeType.MERGE, nullable = false)
    @JoinColumn(name = "resultId")
    private List<Component> component = new ArrayList<>();
}

@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
    @Column(name = "result_id", insertable = false, updatable = false, nullable = false)
    private String resultId;
}

创建双向实体的正确方法是这样。

@Entity
@Table(name = "result")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Result extends AbstractEntity {

    @OneToMany(cascade = CascadeType.MERGE, mappedBy="result")
    private List<Component> component = new ArrayList<>();
}

@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
    @ManyToOne(targetEntity = Result.class)
    @JoinColumn(name = "result_id")  //result_id is the column name (foreign key) in cmpt table
    private Result result;

    @Column(name = "result_id", insertable = false, updatable = false)
    private String resultId;
}

这将确保只有一个双向关系(而不是两个单向关系等)。 让我知道您是否还有其他期望。

更新1:

您可以按上面指定的那样向实体添加另一个键。 您将以字符串的形式获得外键。 但是您需要记住,不应删除JoinColumn的实际映射。 我已经测试了上面的配置,它似乎对我有用。

您必须将一个实体声明为以@ManyToOne注释的字段。 我也认为在您的情况下,您应该将@Join列放在Component端:

@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
    @ManyToOne
    @JoinColumn(name = "resultId")
    private Result result;
}

现在您不需要targetEntity属性。

同时删除了@JoinColumn@OneToMany和添加mappedBy属性:

@Entity
@Table(name = "result")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Result extends AbstractEntity {

    @OneToMany(cascade = CascadeType.MERGE, mappedBy="result")
    private List<Component> component = new ArrayList<>();
}

我认为您必须从Component.java类中删除@ManyToOne(targetEntity = Result.class)批注,并且当您尝试保存数据时,首先必须使用save方法保存Result ,然后通过save方法将返回的resultId设置为此使用setter和getter在组件实体中的resultId ,然后保存组件

这是为我工作的解决方案:

@Entity
@Table(name = "result")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Result extends AbstractEntity {

    @OneToMany(cascade = CascadeType.MERGE, nullable = false)
    @JoinColumn(name = "resultId")
    private List<Component> component = new ArrayList<>();
}

@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
    @Column(name = "result_id", insertable = false, updatable = false, nullable = false)
    private String resultId;
}

暂无
暂无

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

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