将单个表映射到JPA中的可嵌入集合

acv*_*vcu 5 java hibernate jpa

我有一个相当独特的情况,试图将单个表映射到JPA中的多个实体.我已经阅读了@Embeddable和@ElementCollection,但我不确定如何在我的情况下使用它们(或者如果可以的话).一个数据库表包含课程信息.表格中可以有行,除了一些值(例如房间号和日期)外,课程中的所有内容都相同.例如:

TERM_CODE   SUBJECT_CODE    ROOM    DAY    INSTRUCTOR_ID
201220      EGRE            0101    TR     123
201220      EGRE            0103    W      124
Run Code Online (Sandbox Code Playgroud)

有没有办法可以从上面的两行中提取数据,并将公共数据放在一个对象中,将不同的值放在单独对象的集合中?这是我希望如何定义类的示例:

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

CourseSchedule:

@Embeddable
public class CourseSchedule {
     private String room;
     private String day;

      public String getRoom() {
       return room;
      }

      public void setRoom(String room) {
       this.room = room;
      }

      public String getDay() {
       return day;
      }

      public void setDay(String day) {
       this.day = day;
      }

      public String getInstructorId() {
       return instructorId;
      }

      public void setInstructorId(String instructorId) {
       this.instructorId = instructorId;
      }
}
Run Code Online (Sandbox Code Playgroud)

我也很困惑,一旦我将它们映射到我的JPQL在这种情况下会是什么样子.

编辑:

如果我将@Id添加到TERM_CODE列,则返回一个没有Hibernate错误的Course对象,但属于Course的CourseSchedule Collection为null.

编辑2:

我试图玩弄处理场和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;

    ...

}
Run Code Online (Sandbox Code Playgroud)

(CourseIdCourseScheduleId是用于复合ID的简单类.)上面的映射返回以下错误:

org.hibernate.MappingException: Foreign key (FK82D03688F590EF27:course_table [TERM_CODE,SUBJECT_CODE])) must have same number of columns as the referenced primary key (course_table [ROOM,DAY,INSTRUCTOR_ID)
Run Code Online (Sandbox Code Playgroud)

如果有助于使课程更容易,我不需要将CourseSchedule引回课程.

有任何想法吗?我唯一的另一个想法是将它们定义为完全独立的实体(未连接),然后以某种方式使用JPQL将它们映射到一起.

bva*_*sen 3

我一直在尝试一些事情,最接近你想要的就是这个(检查类setCourse中的设置器CourseSchedule):

课程

@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;
 }
}
Run Code Online (Sandbox Code Playgroud)

课程安排

@Entity(name="Course")
public class CourseSchedule {
private String room;
private String day;

@Id
@GeneratedValue
private int id;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

@Embedded
private Course course;

public Course getCourse() {
    return course;
}

public void setCourse(Course course) {
    course.schedule.add(this);
    this.course = course;
}

public String getRoom() {
    return room;
}

public void setRoom(String room) {
    this.room = room;
}

public String getDay() {
    return day;
}

public void setDay(String day) {
    this.day = day;
}
}
Run Code Online (Sandbox Code Playgroud)

生成的数据库表

id    subject_code    term_code    day    room
1      "EGRE"           201220     "TR"   "0101"
2      "EGRE"           201220     "W"    "0103"
Run Code Online (Sandbox Code Playgroud)

基本上相反。它并不完全符合您的期望,但它可能会激发您找到更好的解决方案,如果您有更多想法或发现一些有趣的东西,请随时告诉我......