[英]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.