2013-03-06 17 views
4

我想用我的QuestionCompletion類的所有子元素保持對象。其中一個孩子有一個複合主鍵。作爲這個主鍵的一部分,我還有另一個實體的外鍵。結果我收到此錯誤:使用外鍵級聯保存實體對象作爲複合主鍵的一部分

Exception caught during request processing: javax.ejb.EJBTransactionRolledbackException: 
could not set a field value by reflection setter of com.example.model.domain.QuestionCompletionAnswerPK.questionCompletionId 
javax.ejb.EJBTransactionRolledbackException: could not set a field value by reflection 
setter of com.example.model.domain.QuestionCompletionAnswerPK.questionCompletionId 

而最後的「致」當然是NullPointerException的:

Caused by: java.lang.NullPointerException 

這是我的代碼部分。最後一行會導致錯誤。

QuestionCompletion questionCompletion = new QuestionCompletion(); 
List<QuestionCompletionAnswer> answers = new ArrayList<QuestionCompletionAnswer>(); 
for (;;) { // loop isn't important; it's loop for answers 
    ExtendedQuestion extendedQuestion = new ExtendedQuestion(); 
    extendedQuestion.setId(extendedQuestionId); //extendedQuestionId is known to me in that place 
    for (;;) { // loop isn't important; it's loop for question answers 
     //questionCompletion and extendedQuestion are popualted here 
     QuestionCompletionAnswer questionCompletionAnswer = new QuestionCompletionAnswer(); 
     questionCompletionAnswer.setQuestionCompletion(questionCompletion); 
     questionCompletionAnswer.setExtendedQuestion(extendedQuestion); 
     answers.add(questionCompletionAnswer); 
    } 
} 
questionCompletion.setAnswers(answers); 
questionCompletionService.saveOrMerge(questionCompletion); 

這是我的基本實體類我想堅持所有的孩子元素。我意識到List<QuestionCompletionAnswer>會導致問題。我用cascade = CascadeType.ALL也允許堅持孩子的元素。

@javax.persistence.Entity 
@org.hibernate.annotations.Entity(dynamicUpdate = true) 
@Table(name = "question_completion") 
public class QuestionCompletion implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "question_completion_gen") 
    @SequenceGenerator(name = "question_completion_gen", sequenceName = "question_completion_id_seq") 
    @Column(name = "question_completion_id") 
    private Long id; 

    @OneToMany(cascade = CascadeType.ALL) 
    @JoinColumn(name = "extended_question_id") 
    protected List<QuestionCompletionAnswer> answers; 
} 

這是我的課 - QuestionCompletionAnswer類的主鍵。

@Embeddable 
public class QuestionCompletionAnswerPK implements Serializable { 

    @Column(name = "question_completion_id") 
    protected Long questionCompletionId; 

    @Column(name = "extended_question_id") 
    protected Long extendedQuestionId; 
} 

這是使用我的EmbeddedId的類。屬性questionCompletionIdquestionCompletionId是另一些實體的外鍵,因此我也在下面將這些實體的整個對象與@MapsId註釋放在一起。

@javax.persistence.Entity 
@org.hibernate.annotations.Entity(dynamicUpdate = true) 
@Table(name = "extended_question_answer") 
public class QuestionCompletionAnswer implements Serializable { 

    @EmbeddedId 
    private QuestionCompletionAnswerPK id; 

    @ManyToOne 
    @MapsId(value = "questionCompletionId") 
    @JoinColumn(name = "question_completion_id", nullable = false, insertable = false, updatable = false) 
    protected QuestionCompletion questionCompletion; 

    @ManyToOne 
    @MapsId(value = "extendedQuestionId") 
    @JoinColumn(name = "extended_question_id", nullable = false, insertable = false, updatable = false) 
    protected ExtendedQuestion extendedQuestion; 
} 

您能否告訴我我的註釋是否正確?也許我混合了幾種方法。或者我不能在這種情況下堅持我的基本對象與它的所有子元素。

編輯

現在我的映射是這樣的:

@javax.persistence.Entity 
@org.hibernate.annotations.Entity(dynamicUpdate = true) 
@Table(name = "question_completion") 
public class QuestionCompletion implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "question_completion_gen") 
    @SequenceGenerator(name = "question_completion_gen", sequenceName = "question_completion_id_seq") 
    @Column(name = "question_completion_id") 
    private Long id; 

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "questionCompletion") 
    protected List<QuestionCompletionAnswer> answers; 
} 

QuestionCompletionAnswerPK類的代碼是一樣的。

@javax.persistence.Entity 
@org.hibernate.annotations.Entity(dynamicUpdate = true) 
@Table(name = "extended_question_answer") 
public class QuestionCompletionAnswer implements Serializable { 

    @EmbeddedId 
    private QuestionCompletionAnswerPK id; 

    @ManyToOne(cascade = CascadeType.PERSIST) 
    @MapsId(value = "questionCompletionId") 
    @JoinColumn(name = "question_completion_id", nullable = false) 
    protected QuestionCompletion questionCompletion; 

    @ManyToOne 
    @MapsId(value = "extendedQuestionId") 
    @JoinColumn(name = "extended_question_id", nullable = false) 
    protected ExtendedQuestion extendedQuestion; 
} 

有了這個映射,我仍然得到相同的異常。

編輯#2 然而,當我以這種方式改變了QuestionCompletionAnswer類:

@javax.persistence.Entity 
@org.hibernate.annotations.Entity(dynamicUpdate = true) 
@Table(name = "extended_question_answer") 
public class QuestionCompletionAnswer implements Serializable { 

    @EmbeddedId 
    private QuestionCompletionAnswerPK id; 

    @ManyToOne(cascade = CascadeType.PERSIST) 
    @JoinColumn(name = "question_completion_id", nullable = false, insertable = false, updatable = false) 
    protected QuestionCompletion questionCompletion; 

    @ManyToOne 
    @JoinColumn(name = "extended_question_id", nullable = false, insertable = false, updatable = false) 
    protected ExtendedQuestion extendedQuestion; 
} 

我得到這個異常:

Caused by: org.hibernate.id.IdentifierGenerationException: null id generated 
for:class com.example.model.domain.QuestionCompletionAnswer 
+1

不要將@joincolumn添加到onetomany映射。改爲將其標記爲通過擴展問題映射映射。同時刪除manytoone joincolumn def中的updatable = false insertable = false,如mapsid註釋所暗示的那樣。 – Chris 2013-03-06 21:28:17

+0

@Chris感謝您的評論。我已經改變了你所描述的那些線條,但我仍然遇到同樣的錯誤。 – woyaru 2013-03-06 21:58:18

+0

你應該改變上面的代碼,然後顯示你現在有什麼,因爲上面的模型是錯誤的。同時顯示NPE堆棧以查看它來自何處,並確保持續/合併引用的問題,以便分配ID。你可能需要在questionCompletion映射上設置級聯持久化 – Chris 2013-03-07 00:16:34

回答

2

編輯1,2仍然不正確。您需要在關係中指定mapsid,或者您必須使用您自己的值在嵌入ID中設置字段。並且,當您使用mapsid時,不應將加入列標記爲insertable = false,否則jpa不能爲您插入值。我看到的最後一個問題是,新問題沒有被保留,因此它沒有得到一個指定了答案可以引用的標識符 - 您需要明確地將新問題保留在for循環中,或者在答案中標記關係以級聯堅持。

+0

我已經實施了您所描述的更改。但是保存'QuestionCompletionAnswer'仍然存在問題 - 同樣的例外。對我來說'cascade = CascadeType.ALL'在這種情況下不起作用。我將明確保存它。然而,如果沒有'QuestionCompletionAnswer'對象列表,'QuestionCompletion'正在保存沒有任何問題。 – woyaru 2013-03-07 14:23:08

+0

錯誤狀態說明NPE正在嘗試設置QuestionCompletionAnswerPK中的字段。您的QuestionCompletionAnswer是否已將QuestionCompletionAnswerPK分配給ID?也許發佈完整的NPE堆棧跟蹤如果分配一個新的QuestionCompletionAnswerPK不創建新的時候QuestionCompletionAnswer沒有幫助。 – Chris 2013-03-07 18:24:31

1

爲什麼混合jpa和hibernate註釋?單獨的jpa註釋就足夠了。 與下面的映射嘗試(I除去類QuestionCompletionAnswerPK):

QuestionCompletion.java

@Entity 
@Table(name = "question_completion") 
public class QuestionCompletion { 

    @Id 
    @SequenceGenerator(name = "question_completion_gen", sequenceName = "question_completion_id_seq") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "question_completion_gen") 
    @Column(name = "question_completion_id") 
    private Long id; 

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "questionCompletion") 
    protected List<QuestionCompletionAnswer> answers; 
} 

QuestionCompletionAnswer.java

@Entity 
@Table(name = "extended_question_answer") 
public class QuestionCompletionAnswer implements Serializable { 

    @Id 
    @ManyToOne 
    @JoinColumn(name = "question_completion_fk") 
    private QuestionCompletion questionCompletion; 

    @Id 
    @ManyToOne 
    @JoinColumn(name = "extended_question_fk") 
    private ExtendedQuestion extendedQuestion; 
} 

利用這種映射,我運行以下測試用例和它的工作:

QuestionCompletion questionCompletion = new QuestionCompletion(); 
ExtendedQuestion extendedQuestion = new ExtendedQuestion(); 
QuestionCompletionAnswer answer = new QuestionCompletionAnswer(); 
answer.setQuestionCompletion(questionCompletion); 
answer.setExtendedQuestion(extendedQuestion); 
questionCompletion.setAnswers(Collections.singletonList(answer)); 
... 
session.save(extendedQuestion); 
session.save(questionCompletion); 
相關問題