2016-03-03 32 views
2

我的問題很多關係是相當類似以下內容:JPA不會從一個插入新的孩子的,當我們使用合併

JPA: How do I add new Items to a List with a OneToMany annotation

Why merging is not cascaded on a one to many relationship

JPA with JTA: Persist entity and merge cascaded child entities

我也有一個看在Wikibooks,但仍然無法解決我的問題

所以,我的問題是我有一個父類與孩子,當我添加一個新的孩子,並使用entityManager.merge(父)來更新新的孩子沒有插入,我得到一個錯誤的空主鍵。

我能夠創建一個父母與我想要的任何孩子,並更新這些孩子,但不添加一個新的孩子。

例子:

@Entity 
public class Parent { 
    private String name; 
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) 
    private List<Child> children; 
} 
@Entity 
public class Child { 
    private String name; 
    @ManyToOne 
    private Parent parent; 
} 

如果我創建了一些孩子,它工作正常父。如果我更新孩子的屬性它工作正常,如果我添加一個新的孩子父母它不起作用。

public void foo(){ 

    Parent parent = new Parent(); 
    List<Child> children = new ArrayList<Child>(); 
    children.add(new Child()); 
    children.add(new Child()); 
    children.add(new Child()); 
    parent.setChildren(children); 
    //it works 
    entityManager.persist(parent); 

    //and lets say that I have updated some attributes 
    changeAttributesValues(parent); 
    changeAttributesValues(children); 
    //it still working and the values are updated properly 
    entityManager.merge(parent); 

    //but if I add some child 
    List<Child> children = parent.getChildren(); 
    children.add(moreOneChild); 
    parent.setChildren(children); 
    entityManager.merge(parent); 
    //here I got an error saying that jpa cannot insert my attribute because my PK is null 
} 

注:我的PK是一個複合鍵(可以在這個例子中說,這是idFromParent + idCompany)提前

感謝。

EDIT

我解決了這個問題取出複合物鍵和添加一個自動生成的ID。我發佈了我的真實代碼以及我所做的工作。有了這個代碼,

@Entity 
public class Serie implements Serializable{ 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SERIE_ID_SEQ") 
    @SequenceGenerator(name = "SERIE_ID_SEQ", sequenceName = "real.serie_id_seq") 
    @Column(name = "idserie") 
    private Long id; 

    @Basic 
    @Column(name = "nmserie") 
    private String nmSerie; 

    @OneToMany(mappedBy = "serie", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) 
    private List<SerieExercise> serieExercises; 

    @ManyToOne 
    @JoinColumn(name = "idtrainning") 
    private Trainning Trainning; 
} 

@Entity 
public class SerieExercise implements Serializable{ 

    @Basic 
    @Column(name = "nrrepetition") 
    private int nrRepetition; 

    @Column(name = "tminterval") 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date tmInterval; 

    @Id 
    @Basic 
    @Column(name = "nrorder") 
    private Integer nrOrder; 

    @Id 
    @ManyToOne 
    @JoinColumn(name = "idexercise") 
    private Exercise exercise; 

    @Id 
    @ManyToOne 
    @JoinColumn(name = "idserie") 
    private Serie serie; 
} 

有了這個代碼,我得到這個錯誤,當我嘗試在我的列表中插入一個更SerieExercise:

Caused by: org.postgresql.util.PSQLException: ERRO: ERROR: null value in column "nrorder" violates not-null constraint 
    Detail: Failing row contains(null, 10, null, null, null). 
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270) 
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998) 
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255) 
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:570) 
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:420) 
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:366) 
    at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:493) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208) [hibernate-core-4.3.7.Final.jar:4.3.7.Final] 
    ... 132 more 

我有調試和值之前,我打電話entityManager.merge( )不爲空。我正在使用休眠提供程序。我可以在我的列表中插入一份SerieExercise,並且可以更新這些值,但無法在列表中添加新的SerieExercise。

要解決我做了這些變化:

@Entity 
public class SerieExercise implements Serializable{ 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SER_EXER_ID_SEQ") 
    @SequenceGenerator(name = "SER_EXER_ID_SEQ", sequenceName = "realvida.ser_exer_id_seq") 
    @Column(name = "idserieexercicio") 
    private Long id; 

    @Basic 
    @Column(name = "nrrepetition") 
    private int nrRepetition; 

    @Column(name = "tminterval") 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date tmInterval; 

    //@Id 
    @Basic 
    @Column(name = "nrorder") 
    private Integer nrOrder; 

    //@Id 
    @ManyToOne 
    @JoinColumn(name = "idexercise") 
    private Exercise exercise; 

    //@Id 
    @ManyToOne 
    @JoinColumn(name = "idserie") 
    private Serie serie; 
} 

有誰知道爲什麼會發生?我可以使用複合鍵進行這項工作嗎?

讓我知道你是否需要更多信息。

+0

您是否在moreOneChild中設置了父級?你能舉一個更簡單的例子嗎? –

+0

對不起,現在編輯代碼。看起來問題與組合主鍵有關。我仍在研究。 –

+0

我可以讓你的保存序列工作,所以沒有什麼不對。你需要製作一個可重現的問題。如果你有一個複合主鍵,並且你得到了一個關鍵違規,那就需要你的問題的基礎 –

回答

0

我覺得你的孩子端映射看起來我錯了。你必須保持這樣的這種@ManyToOne關係:

@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL) 
@JoinColumn(name="idParent", nullable=false) 
private Parent parent; 

我的意思是,通常在必須使用@JoinColumn一個@ManyToOne關係的業主方。也許不值一提,但值得一提。此外,我們希望看到完整的代碼和完整的堆棧跟蹤,尤其是兒童ID映射(複合ID可能是或不是理由,但請填寫完整代碼)。當涉及到ID再生時,有時底層數據庫和JPA實現庫可能很重要。你在使用EclipseLink,Toplink或其他東西嗎?

+0

是的,這個問題與組合鍵有關。我已將組合鍵更改爲「自動生成的ID」,它解決了問題。非常感謝你。 –

+0

我編輯了我的真實代碼和錯誤的帖子,你知道我能做些什麼來使它與複合鍵一起工作嗎?我的映射有什麼問題嗎?我可以正確堅持並編輯持續的值,但不能添加新的「SerieExercise」。 –

+0

我想你應該發佈你的CompositeID代碼,你想要映射哪個字段等,如果你還想添加一個CompositeID。但是,如果你對簡單ID感到滿意,那很好......實際上我通常不使用複合ID,也沒有看到很多情況下它真的有必要。 – FaithReaper

0

這行代碼看起來我錯了:

parent.addChildren(moreOneChild); 

我本來以爲應該是這樣的:

List<Child> children = parent.getChildren(); 
children.add(moreOneChild); 
entityManager.merge(parent);