Hibernate 连接具有多个主键的表

Hibernate joining tables with multiple primary keys

我已经弄清楚如何使用单个主键连接 2 table。但现在我需要加入 4 tables 和其中一些 table 与复合主键。

这是我的table照片

我想加入他们,所以我为他们生成 类:

// Record
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "record")
public class Record implements java.io.Serializable{
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "student_id")
    private Integer studentId;

    @Id
    @Column(name = "exam_id")
    private Integer examId;

    @Column(name = "total_score")
    private Integer totalScore;

    @Column(name = "student_score")
    private Integer studentScore;

    @Column(name = "submission_id")
    private Integer submissionId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "student_id")
    private Student student;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "submission_id")
    private Submission submission;
}

// Submission
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "submission")
public class Submission implements java.io.Serializable{
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "submission_id")
    private Integer submissionId;

    @Id
    @Column(name = "question_id")
    private Integer questionId;

    @Column(name = "stu_answer")
    private String stuAnswer;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "submission")
    private Record record;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "submission")
    private Set<Question> question;


}

// Question
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "question")
public class Question implements java.io.Serializable{
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    @Column(name = "question_id")
    private Integer questionId;

    @Column(name = "content")
    private String content;

    @Column(name = "score")
    private Integer score;

    @Column(name = "is_delete")
    private Integer isDelete;

    @Column(name = "option_id")
    private Integer optionId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "submission_id")
    private Submission submission;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "optional_id")
    private Optional optional;
}

// Optional
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "optional")
public class Optional implements java.io.Serializable{
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    @Column(name = "option_id")
    private Integer optionId;

    @Column(name = "content")
    private String content;

    @Column(name = "is_delete")
    private Integer isDelete;

    @Column(name = "answer")
    private String answer;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "optional")
    private Question question;
}

// Final class to store information
public class RcdSubQuesOpt {
    private Integer studentId;

    private Integer examId;

    private Integer questionId;

    private String stuAnswer;

    private String qContent;

    private String oContent;

    private String answer;
}

这是 JPA 的代码

@Override
    public List<RcdSubQuesOpt> getRcdSubQuesOpt(int studentID, int examId) {
        Session session = this.getSession();
        List<RcdSubQuesOpt> results;
        Transaction transaction = null;

        try {
            transaction = session.beginTransaction();
            CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
            CriteriaQuery<RcdSubQuesOpt> criteriaQuery = criteriaBuilder.createQuery(RcdSubQuesOpt.class);

            // Try to join tables
            Root<Record> pRoot = criteriaQuery.from(Record.class);
            pRoot.join("submission", JoinType.INNER);
            pRoot.join("question", JoinType.INNER);
            pRoot.join("optional", JoinType.INNER);
            criteriaQuery.multiselect(
                    pRoot.get(columns in RcdSubQuesOpt Class......));

            // Try to add constraints
            Predicate predicate = pRoot.get("examId").in(Arrays.asList(1));
            criteriaQuery.where(predicate);

            // try to do queries
            results = session.createQuery(criteriaQuery).getResultList();
            transaction.commit();

        } catch (Exception e) {
            results = null;
            if (transaction != null) {
                transaction.rollback();
            }
        } finally {
            session.close();
        }

        return results;
    }

但是hibernate抛出如下错误:

Enitial SessionFactory creation failedA Foreign key refering com.domain.Submission from com.domain.Record has the wrong number of column. should be 2

Exception in thread "main" java.lang.ExceptionInInitializerError

我认为这是复合主键问题。但是我搜索的解决方案不是suitable来解决的。有人给我一些建议吗?谢谢!

要引用复合主键,您需要使用 @JoinColumns(复数)。

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumns({
       @JoinColumn(name = "sub_submission_id", referencedColumnName = "submission_id"),
       @JoinColumn(name = "sub_question_id", referencedColumnName = "question_id")
   })
   private Submission submission;

但是,我必须承认,我不理解您的模型 - 特别是为什么 Submissionquestion_id 具有复合 PK。看起来一个Submission有很多Questions,为什么要把question_id作为提交PK的一部分

也许,我遗漏了什么,因为图表不是完全可见的。