2012-02-16 25 views
5

Tôi có một tình huống khá độc đáo khi cố gắng ánh xạ một bảng đơn thành nhiều thực thể trong JPA. Tôi đã đọc về @Embeddable và @ElementCollection, nhưng tôi không chắc chắn làm thế nào để sử dụng chúng trong tình huống của tôi (hoặc nếu tôi có thể). Một bảng cơ sở dữ liệu chứa thông tin khóa học. Có thể có các hàng trong bảng trong đó mọi thứ trong Khóa học giống nhau ngoại trừ một vài giá trị, chẳng hạn như số phòng và ngày. Ví dụ:Lập bản đồ Bảng đơn thành Bộ sưu tập có thể nhúng trong JPA

TERM_CODE SUBJECT_CODE ROOM DAY INSTRUCTOR_ID 
201220  EGRE   0101 TR  123 
201220  EGRE   0103 W  124 

Có cách nào để có thể lấy dữ liệu từ hai hàng như trên và đặt dữ liệu chung trong một đối tượng và các giá trị khác trong Bộ sưu tập các đối tượng riêng biệt? Dưới đây là một ví dụ về cách tôi muốn có các lớp học định nghĩa:

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

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

Tôi cũng bối rối như những gì JPQL của tôi sẽ như thế nào trong tình huống này một lần tôi nhận được chúng ánh xạ.

EDIT:

Nếu tôi thêm @ id đến cột TERM_CODE, một đối tượng Khóa học được trả về mà không có lỗi Hibernate, nhưng bộ sưu tập CourseSchedule đó là một phần của khóa học là null.

EDIT 2:

Tôi đã cố gắng để chơi xung quanh với điều trị Course và CourseSchedule như hai bảng riêng biệt (mặc dù họ không), nhưng tôi dường như không thể làm cho họ gia nhập sử dụng @OneToMany và @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; 

    ... 

} 

(Các CourseIdCourseScheduleId các lớp học đơn giản sử dụng cho ID composite.) Các bản đồ trên trả lại lỗi sau:

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) 

Tôi không cần CourseSchedule giới thiệu về khóa học nếu giúp dễ dàng hơn.

Bất kỳ ý tưởng nào? Suy nghĩ duy nhất khác của tôi là xác định chúng như là các thực thể hoàn toàn riêng biệt (không tham gia), và sau đó bằng cách nào đó ánh xạ chúng lại với nhau bằng cách sử dụng JPQL.

+0

Tôi đoán đây là DB hiện tại? vì vậy bạn không thể sử dụng khóa ngoài cho TERM_CODE trong bảng CourseSchedule? Tôi có thể có lý do chính đáng để làm điều này, nhưng bạn sao chép khá nhiều dữ liệu chỉ để lưu trữ thông tin về ROOM và DAY. Báo cáo ngủ đông khi bạn ánh xạ nó như thế nào? – bvanvelsen

+0

Thật không may tôi không thể thay đổi cơ sở dữ liệu, và tất cả trong một bảng. Tôi ước gì tôi có thể thuyết phục họ bình thường hóa nó, nhưng điều đó không xảy ra. – acvcu

+0

Nếu tôi chạy nó ở dạng hiện tại của nó, tôi nhận được lỗi "Không có định danh được chỉ định cho thực thể: Khóa học", mà tôi gần như lẽ ra phải có dự kiến. Một vấn đề nữa là bảng cơ sở dữ liệu không định nghĩa khóa chính. – acvcu

Trả lời

3

Tôi đã cố gắng điều gì đó, và gần nhất tôi nhận được những gì bạn muốn là thế này (kiểm tra setter setCourse trong lớp CourseSchedule):

Khóa học

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

CourseSchedule

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

bảng cơ sở dữ liệu đã tạo

id subject_code term_code day room 
1  "EGRE"   201220  "TR" "0101" 
2  "EGRE"   201220  "W" "0103" 

Về cơ bản, theo cách khác. Nó không phải là hoàn toàn những gì bạn mong đợi, nhưng nó có thể truyền cảm hứng cho bạn cho một giải pháp tốt hơn, xin vui lòng giữ cho tôi cập nhật nếu bạn có thêm ý tưởng hoặc tìm thấy một cái gì đó thú vị ...

+0

Đó không phải là một ý tưởng tồi, tôi sẽ cho nó một cái nhìn. Vấn đề duy nhất là cách bạn có nó, tôi sẽ không phải tạo ra một bảng cơ sở dữ liệu? Tôi có lẽ đã đọc/ghi truy cập vào cơ sở dữ liệu, nhưng tôi không sở hữu dữ liệu và không thể tạo bất kỳ điều gì mới trên máy chủ. Nó cũng không cho phép tôi có CourseSchedule như một bộ sưu tập các khóa học, điều này có ý nghĩa logic hơn khi sử dụng các đối tượng từ phối cảnh của máy khách. – acvcu

+0

Tôi đã quay trở lại và cố gắng này w/ra ID tạo ra, nhưng tôi không thể nhận được bất kỳ truy vấn của tôi để trở về các khóa học mà không có bộ sưu tập CourseSchedule null. Thay vì sử dụng ID đã tạo, tôi đã sử dụng ID tổng hợp trên CourseSchedule. – acvcu

0

Đây là những gì tôi đã đưa ra (trừ khi ai đó đi lên với một ý tưởng tốt hơn):

Bản đồ Khóa học và CourseSchedule vào bảng tương tự, nhưng không tham gia cùng họ:

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

    ... 

} 

Trong đối tượng DAO, truy vấn riêng khóa học và khóa họcSchedule và thêm bộ sưu tập CourseSchedule vào khóa học:

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()); 
    } 
} 
Các vấn đề liên quan