2017-08-11 155 views
0

我試圖在Hibernate中映射雙向(一對多和多對一)關係。嘗試保存結果時發生錯誤。映射雙向一對多Hibernate實體

我們得到的錯誤是:

產生的原因:org.hibernate.PropertyValueException:非空屬性引用null或瞬時值:在org.hibernate作爲com.example.Component.resultId .engine.internal.Nullability.checkNullability(Nullability.java:92)

Result下面的源代碼可以具有許多Component S和許多Component S可屬於單個Result。其中一個要求是resultIdResult必須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; 
} 
+0

什麼是ID字段的實體類型? '@ OneToMany'上的'@ JoinColumn'註釋是無用的,而類型爲String的字段上的'@ ManyToOne'註解也是無用的,因爲你只能在實體上使用這個註解。 – ujulu

回答

1

正確的方法來建立一個雙向的實體是這個解決方案。

@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的實際映射。我已經測試了上述配置,它似乎適用於我。

+0

'Component'中的'resultId' **必須是'String' – breaktop

+0

您可以從result.getId()no訪問resultId? – yaswanth

+0

我理解你的解決方案,但這是一個超出我們控制的限制。 'Component'中的'resultId' **必須是'String' – breaktop

0

您必須將實體聲明爲使用@ManyToOne註釋的字段。此外,我認爲你的情況,你應該把@Join列在組件端:

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

現在你不需要的targetEntity attrbute。

而且從@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<>(); 
} 
+0

我理解你的解決方案,但這是一個超出我們控制範圍的限制。 'Component'中的'resultId' **必須是'String' – breaktop

0

我認爲你必須從組件刪除註釋@ManyToOne(targetEntity = Result.class)。java的類,當你試圖先保存數據,你必須使用Save方法保存結果,然後你得到了resultId返回的保存方法,使用setter和getter設置此在組件實體resultId然後保存組件

0

這裏是爲我工作的解決方案:

@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; 
}