【发布时间】:2013-02-21 17:34:04
【问题描述】:
我想将我的 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 的课程。属性questionCompletionId 和questionCompletionId 是其他一些实体的外键,所以我还用@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
【问题讨论】:
-
不要将@joincolumn 添加到onetomany 映射中。而是通过扩展问题映射将其标记为映射。同时删除 manytoone joincolumn def 上的 updatable=false insertable=false,因为 mapid 注释所暗示的。
-
@Chris 感谢您的评论。我已经改变了你描述的那几行,但我仍然遇到同样的错误。
-
您应该更改上面的代码以显示您现在拥有的内容,因为上面的模型是错误的。还要显示 NPE 堆栈以查看它的来源,并确保您正在持久化/合并引用的问题,以便分配它们的 ID。您可能需要在 questionCompletion 映射上设置 cascade persist
-
我的错误恰好出现在保存
questionCompletion-Serializable id = getSession().save(questionCompletion);的那一刻,所以事实上我没有得到这个实体的 id。 -
@Chris 我已经更新了我的问题。我仍然遇到同样的异常。
标签: java spring hibernate jpa spring-mvc