java - 将具有外键的实体对象级联保存为复合主键的一部分

标签 java spring hibernate jpa spring-mvc

我想保留我的 QuestionCompletion 对象包含所有子元素的类。其中一个 child 有一个复合主键。作为这个主键的一部分,我还有另一个实体的外键。结果我收到了这个错误:

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

这是我的类(class) - 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;
}

我得到了那个异常(exception):

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 循环中明确保留新问题或在答案中标记关系级联持续存在。

关于java - 将具有外键的实体对象级联保存为复合主键的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15255615/

相关文章:

java - 在 Javamail 中不显示附件

xml - Hibernate 写入 XML 数据库

java - 如何使用 Hibernate 从非所有者端删除 @ManyToMany 关联中的关系?

java - 尝试使用 UTF-16 字符代码打印 "white smiling face"\u263A

java - 套接字上的客户端的高性能多线程

java - Scala/Java 中的大字符串上的简单正则表达式失败并出现 stackoverflow

java - Spring - PropertiesPlaceholderConfigurer 找不到属性文件

java - 错误: Could not find or load main class Main in CMD

java - 用Spring实现单例模式的好方法

java - Spring JPA 的@transactional 注释不起作用