5

QuestionCompletionクラスのオブジェクトをすべての子要素で永続化したいと考えています。これらの子の 1 つに複合主キーがあります。この主キーの一部として、別のエンティティへの外部キーもあります。その結果、次のエラーが発生します。

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

そして、これは my を使用するクラス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
4

2 に答える 2

3

編集1と2はまだ正しくありません。リレーションシップで mapsid を指定するか、埋め込み ID のフィールドに自分で値を設定する必要があります。また、mapsid を使用する場合、join 列に insertable=false のマークを付けないでください。そうしないと、jpa が値を挿入できません。私が見る最後の問題は、新しい質問が永続化されていないため、回答が参照できるIDが割り当てられないことです.forループで新しい質問を明示的に永続化するか、回答の関係をマークする必要がありますカスケードが持続します。

于 2013-03-07T13:03:09.353 に答える
1

なぜ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);
于 2013-03-14T16:19:09.657 に答える