Java 在JPA中将单个表映射到可嵌入集合
在JPA中,我有一个非常独特的情况,试图将一个表映射到多个实体。我读过@Embeddeble和@ElementCollection,但我不确定在我的情况下如何使用它们(或者如果可以的话)。one数据库表保存课程信息。表中可以有行,其中课程中的所有内容都是相同的,除了一些值,例如房间号和日期。例如:Java 在JPA中将单个表映射到可嵌入集合,java,hibernate,jpa,Java,Hibernate,Jpa,在JPA中,我有一个非常独特的情况,试图将一个表映射到多个实体。我读过@Embeddeble和@ElementCollection,但我不确定在我的情况下如何使用它们(或者如果可以的话)。one数据库表保存课程信息。表中可以有行,其中课程中的所有内容都是相同的,除了一些值,例如房间号和日期。例如: TERM_CODE SUBJECT_CODE ROOM DAY INSTRUCTOR_ID 201220 EGRE 0101 TR
TERM_CODE SUBJECT_CODE ROOM DAY INSTRUCTOR_ID
201220 EGRE 0101 TR 123
201220 EGRE 0103 W 124
有没有一种方法可以像上面那样从两行中提取数据,并将公共数据放在一个对象中,将不同的值放在一个单独对象的集合中?下面是我希望如何定义类的示例:
@Entity
public class Course implements Serializable {
@Id
@Column(name = "TERM_CODE")
private Long termCode;
@Column(name = "SUBJECT_CODE")
private String subjectCode;
@Embedded
Collection<CourseSchedule> schedule;
public Long getTermCode() {
return termCode;
}
public void setTermCode(Long termCode) {
this.termCode = termCode;
}
public String getSubjectCode() {
return subjectCode;
}
public void setSubjectCode(String subjectCode) {
this.subjectCode = subjectCode;
}
}
我也很困惑,在这种情况下,一旦映射到JPQL,我的JPQL会是什么样子
编辑:
如果我将@Id添加到TERM_CODE列,则返回的课程对象没有Hibernate错误,但作为课程一部分的CourseSchedule集合为null
编辑2:
我曾尝试将Course和CourseSchedule视为两个独立的表(尽管它们不是),但我似乎无法使用@OneToMany和@ManyToOne将它们连接起来
@Entity
@IdClass(CourseId.class)
@Table(name = "course_table")
public class Course implements Serializable {
@OneToMany(mappedBy = "course")
private Collection<CourseSchedule> schedule;
@Id
@Column(name = "TERM_CODE")
private Long termCode;
@Id
@Column(name = "SUBJECT_CODE")
private Long subjectCode;
...
}
@Entity
@IdClass(CourseScheduleId.class)
@Table(name = "course_table")
public class CourseSchedule implements Serializable {
@ManyToOne
@JoinColumns({
@JoinColumn(name="TERM_CODE", referencedColumnName="TERM_CODE"),
@JoinColumn(name = "SUBJECT_CODE", referencedColumnName="SUBJECT_CODE")
})
private Course course;
@Column(name = "TERM_CODE")
private Long termCode;
@Column(name = "SUBJECT_CODE")
private Long subjectCode;
@Id
private String room;
@Id
private String day;
@Id
@Column(name = "INSTRUCTOR_ID")
private String instructorId;
...
}
如果这有助于简化课程,我不需要课程安排,也不需要返回课程
有什么想法吗?我唯一的另一个想法是将它们定义为完全独立的实体(未连接),然后使用JPQL以某种方式将它们映射到一起。我一直在尝试一些事情,最接近您想要的就是这个(检查
CourseSchedule
类中的settersetCourse
:
课程
@Embeddable
public class Course implements Serializable {
@Column(name = "TERM_CODE")
private Long termCode;
@Column(name = "SUBJECT_CODE")
private String subjectCode;
@Transient
Collection<CourseSchedule> schedule = new ArrayList<CourseSchedule>();
public void setSchedule(Collection<CourseSchedule> schedule) {
this.schedule = schedule;
}
public Collection<CourseSchedule> getSchedule() {
return schedule;
}
public Long getTermCode() {
return termCode;
}
public void setTermCode(Long termCode) {
this.termCode = termCode;
}
public String getSubjectCode() {
return subjectCode;
}
public void setSubjectCode(String subjectCode) {
this.subjectCode = subjectCode;
}
}
生成的数据库表
id subject_code term_code day room
1 "EGRE" 201220 "TR" "0101"
2 "EGRE" 201220 "W" "0103"
基本上相反。这并不完全是您所期望的,但它可能会激励您寻找更好的解决方案,如果您有更多想法或发现有趣的内容,请随时向我通报。这是我的想法(除非有人提出更好的想法): 将课程和课程时间表映射到同一个表,但不要将其加入:
@Entity
@IdClass(CourseId.class)
@Table(name = "course_table")
public class Course implements Serializable {
@Transient
private Collection<CourseSchedule> schedule;
@Id
@Column(name = "TERM_CODE")
private Long termCode;
@Id
@Column(name = "SUBJECT_CODE")
private Long subjectCode;
...
}
@Entity
@IdClass(CourseScheduleId.class)
@Table(name = "course_table")
public class CourseSchedule implements Serializable {
@Column(name = "TERM_CODE")
private Long termCode;
@Column(name = "SUBJECT_CODE")
private Long subjectCode;
@Id
private String room;
@Id
private String day;
@Id
@Column(name = "INSTRUCTOR_ID")
private String instructorId;
...
}
@实体
@IdClass(CourseId.class)
@表(name=“课程表”)
公共类课程实现可序列化{
@短暂的
私人收集时间表;
@身份证
@列(name=“TERM\u CODE”)
私人长期守则;
@身份证
@列(name=“主题代码”)
专用长主题代码;
...
}
@实体
@IdClass(CourseScheduleId.class)
@表(name=“课程表”)
公共类CourseSchedule实现可序列化{
@列(name=“TERM\u CODE”)
私人长期守则;
@列(name=“主题代码”)
专用长主题代码;
@身份证
私人弦乐室;
@身份证
私人弦日;
@身份证
@列(name=“讲师ID”)
私有字符串指令ID;
...
}
在DAO对象中,分别查询Course和CourseSchedule,并将CourseSchedule集合添加到课程:
public Collection<Course> getCourses() {
String jpql = "SELECT DISTINCT course FROM Course course";
TypedQuery<Course> typedQuery = entityManager
.createQuery(jpql, Course.class);
// get the Courses and set their schedules
Collection<Course> courses = typedQuery.getResultList();
setCourseSchedules(courses);
return courses;
}
private void setCourseSchedules(Collection<Course> courses) {
// query for getting CourseSchedules
String jpql = "SELECT DISTINCT schedule FROM CourseSchedule schedule "
+ "WHERE schedule.subjectCode = :subjectCode "
+ "AND schedule.termCode = :termCode";
for (Course c : courses) {
TypedQuery<CourseSchedule> typedQuery = entityManager
.createQuery(jpql, CourseSchedule.class)
.setParameter("subjectCode", c.getSubjectCode())
.setParameter("termCode", c.getTermCode());
c.setSchedule(typedQuery.getResultList());
}
}
getCourses()公共集合{
String jpql=“从课程中选择不同的课程”;
TypedQuery TypedQuery=entityManager
.createQuery(jpql,Course.class);
//获取课程并设置他们的时间表
Collection courses=typedQuery.getResultList();
设置课程时间表(课程);
返回课程;
}
私人课程时间表(收集课程){
//查询获取课程时间表
String jpql=“从课程时间表中选择不同的时间表”
+“其中schedule.subjectCode=:subjectCode”
+“和schedule.termCode=:termCode”;
(课程c:课程){
TypedQuery TypedQuery=entityManager
.createQuery(jpql,CourseSchedule.class)
.setParameter(“subjectCode”,c.getSubjectCode())
.setParameter(“termCode”,c.getTermCode());
c、 setSchedule(typedQuery.getResultList());
}
}
我想这是一个现有的数据库?那么您不能在CourseSchedule表中使用术语_代码的外键?我可能有很好的理由这样做,但您复制了相当多的数据,只是为了存储房间和日常信息。当您这样映射它时,hibernate会报告什么?不幸的是,我无法更改数据库,而且它都在一个表中。我希望我能说服他们对其进行规范化,但这并没有发生。如果我以当前的形式运行它,我会得到错误“没有为实体指定标识符:课程”,这几乎是我应该预料到的。另一个问题是数据库表没有定义主键。这不是个坏主意,我来看看。唯一的问题是,按照您的方式,我不需要生成另一个数据库表吗?我可能具有对数据库的读/写访问权限,但我不拥有数据,也无法在服务器上创建任何新内容。它也不允许我将CourseSchedule作为课程集合,这在从客户端角度使用对象时更具逻辑意义。我返回并尝试了这个方法,并删除了生成的ID,但我无法让任何查询返回没有空CourseSchedule集合的课程。我没有使用生成的ID,而是在CourseSchedule上使用了复合ID。
id subject_code term_code day room
1 "EGRE" 201220 "TR" "0101"
2 "EGRE" 201220 "W" "0103"
@Entity
@IdClass(CourseId.class)
@Table(name = "course_table")
public class Course implements Serializable {
@Transient
private Collection<CourseSchedule> schedule;
@Id
@Column(name = "TERM_CODE")
private Long termCode;
@Id
@Column(name = "SUBJECT_CODE")
private Long subjectCode;
...
}
@Entity
@IdClass(CourseScheduleId.class)
@Table(name = "course_table")
public class CourseSchedule implements Serializable {
@Column(name = "TERM_CODE")
private Long termCode;
@Column(name = "SUBJECT_CODE")
private Long subjectCode;
@Id
private String room;
@Id
private String day;
@Id
@Column(name = "INSTRUCTOR_ID")
private String instructorId;
...
}
public Collection<Course> getCourses() {
String jpql = "SELECT DISTINCT course FROM Course course";
TypedQuery<Course> typedQuery = entityManager
.createQuery(jpql, Course.class);
// get the Courses and set their schedules
Collection<Course> courses = typedQuery.getResultList();
setCourseSchedules(courses);
return courses;
}
private void setCourseSchedules(Collection<Course> courses) {
// query for getting CourseSchedules
String jpql = "SELECT DISTINCT schedule FROM CourseSchedule schedule "
+ "WHERE schedule.subjectCode = :subjectCode "
+ "AND schedule.termCode = :termCode";
for (Course c : courses) {
TypedQuery<CourseSchedule> typedQuery = entityManager
.createQuery(jpql, CourseSchedule.class)
.setParameter("subjectCode", c.getSubjectCode())
.setParameter("termCode", c.getTermCode());
c.setSchedule(typedQuery.getResultList());
}
}