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;
但是,我必须承认,我不理解您的模型 - 特别是为什么 Submission
与 question_id
具有复合 PK。看起来一个Submission
有很多Questions
,为什么要把question_id
作为提交PK的一部分?
也许,我遗漏了什么,因为图表不是完全可见的。
我已经弄清楚如何使用单个主键连接 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;
但是,我必须承认,我不理解您的模型 - 特别是为什么 Submission
与 question_id
具有复合 PK。看起来一个Submission
有很多Questions
,为什么要把question_id
作为提交PK的一部分?
也许,我遗漏了什么,因为图表不是完全可见的。