Java 映射双向一对多Hibernate实体

Java 映射双向一对多Hibernate实体,java,spring,hibernate,jpa,spring-jdbc,Java,Spring,Hibernate,Jpa,Spring Jdbc,我试图在Hibernate中映射双向的一对多和多对一关系。尝试保存结果时出现错误 我们得到的错误是: 原因:org.hibernate.PropertyValueException:notnull属性引用空值或暂时值:com.example.Component.resultId 位于org.hibernate.engine.internal.Nullability.checkNullabilityNullability.java:92 根据下面的源代码,一个结果可以有许多组件,并且许多组件可以属

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

我们得到的错误是:

原因:org.hibernate.PropertyValueException:notnull属性引用空值或暂时值:com.example.Component.resultId 位于org.hibernate.engine.internal.Nullability.checkNullabilityNullability.java:92

根据下面的源代码,一个结果可以有许多组件,并且许多组件可以属于一个结果。要求之一是Result中的resultId必须是字符串。这个要求是我们无法控制的

实体源代码示例如下:

@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, 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列放在组件端:

@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
    @ManyToOne
    @JoinColumn(name = "resultId")
    private Result result;
}
现在您不需要targetEntity属性

同时从@OneToMany中删除@JoinColumn并添加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类中删除注释@manytooneargetity=Result.class,当您尝试保存数据时,首先必须使用save方法保存结果,然后获得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;
}

我理解你的解决方案,但这是一个我们无法控制的约束。组件中的resultId必须是StringResultID必须是StringResultID您可以从result.getId访问resultId否?我理解您的解决方案,但这是一个我们无法控制的约束。组件中的resultId必须是一个字符串。感谢您让它工作起来-您的解决方案非常有用。我已经用对我有效的解决方案更新了这个问题。如果对你有效,你能接受答案吗?实体中ID字段的类型是什么?@OneToMany上的@JoinColumn注释是无用的,String类型字段上的@ManyToOne注释也是无用的,因为您只能在实体上使用此注释。
@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;
}