[英]Cascading save Entity objects with Foreign Key as a part of composite Primary Key
我想坚持我的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
ComplempleId和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
编辑1和2仍然不对。 您需要在关系中指定的mapsid,或者您必须自己在嵌入式ID中设置值。 当您使用mapsid时,您不应该将连接列标记为insertable = false或jpa无法为您插入值。 我看到的最后一个问题是新问题没有持久化,所以它没有得到答案可以引用的id - 你需要在for循环中明确地保留新问题或者在答案中标记关系到级联持续存在。
为什么要混用jpa和hibernate注释? 单独的jpa注释就足够了。 尝试使用以下映射(我删除了类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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.