2013-07-18 21 views
0

我們具有一個Java EE JPA映射問題如下所述:使用Hibernate映射多到許多非傳統方法

1)的技術是休眠(V 10也許2.9或以上)和Oracle 11g

2)DB建築師執行類似於下面一個很常見的DB的結構:

COURSE  STUDENT_COURSES   STUDENT_DETAILS 
    ------  ---------------   ------- 
    CR_PK (PK) ST_ID (PK_1, FK_1)  ST_ID (PK) 
        CR_ID (PK_2, FK_2)  FIRST_NAME 
        ROLE      LAST_NAME 
              IS_HAZED 
              NUM_YEARS 
              PRESENDENT_IND 
              DRIVER_LICENSE_NO 

3)的Java EE建築師執行類似於以下一個類層次結構:

Interface StudentService { 
     Student saveStudent(Student student); 
     Student getStudent(StudentId id); 
     void removeStudent(Student student); 
     Set<RookieStudent> getRookies(int courseId); 
     Set<SinorStudent> getSeniors(int courseId); 
     JuniorStudent getStudentBodyPresedent(int courseId) (the result can be a Junior or Senior) 

預計將使用任何方法來實現上述業務服務接口。該界面將最有效地支持UI模型已被業務部門批准的表示層。其餘所需的類層次結構如下:

Class StudentId 
     int studentId; 
     int courseId; 

    Class Student 
     @embededId 
     StudentId id 

     String role; 

     String first_name; 
     String last_name; 
     int num_years; 

    Class RookieStudent extends Student 
     boolean isHazed;      

    Class JuniorStudent extends Student 
     Boolean isPresendent;    

    Class SeniorStudent extends JuniorStudent 
     int age; 
     String driverLicenseNumber; 

4)大部分爲學生和子類的細節將有來自STUDENT_DETAILS表。根據ROLE的值,該類將具有該表中的其他屬性。例如,如果ROLE ='S',則將使用STUDENT_DETAILS.DRIVER_LICENSE_NO中的值填充driverLicenseNumber。

我已經嘗試過這個模型的各種映射,但是Hibernate的實體管理器要麼會映射映射,要麼會產生不正確的結果。有沒有辦法使用JPA映射這個模型?我已經嘗試過使用輔助表的「每個層次的單一表」方法,但生成的Oracle查詢完全錯誤。爲獲得使用業務接口一個大三的學生產生的查詢類似於以下內容:

SELECT c.course_id, 
     c.student_id, 
     d.first_name, 
     d.last_name, 
     c.role, 
     d.num_years, 
     d.presendent_ind, 
    FROM student_courses c 
     left outer join student_details d 
      WITH c.course_id = d.student_id 
    WHERE c.role = 'J' 

這是很容易看到如何編寫正確的查詢,當然,Hibernate正在努力瞭解我們所要求的。如果可能,我們傾向於使用註釋配置。

+1

尋求幫助時緊迫感迫使社區不是一個好的姿態。我們不能不在意你的內部業務發生了什麼,Stack Overflow更多地是以問答形式共享技術知識 – gerrytan

+1

坦率地說,這個實體設計對我來說毫無意義。 Student實體映射student_details表中的一行,然後它不能具有courseId或角色,或者它映射來自student_courses表的一行,然後它具有與課程的ManyToOne關聯和具有另一實體的ManyToOne映射到student_details表。 student_details表中的給定行不能被幾個不同的實體實例映射。我的建議是將每個表映射到一個實體,並在它們之間建立OneToMany/ManyToOne關聯。 –

回答

0

忽略JPA,您嘗試執行的操作在Java中沒有意義。如果你的學生去上了一門不同的課程,那麼大概這個學生在新課堂上的角色可能會有所不同:一個小學生可能會成爲一名大四學生。您不能僅使用Java對象切換角色更改 - 您必須創建一個全新的學生實例。正如JB建議的那樣,讓每個表成爲一個實體。然後,您可以使用student_course實體作爲包裝來訪問Student中符合該類中學生角色的屬性。 juniorRole類型只會暴露您想要存在於JuniorStudent中的字段。

Role類將使用單個表繼承,其中只包含OneToOne課程和OneToOne以供學生使用,並將該角色用作類型鑑別器。然後,訪問方法將訪問studentDetails,並在創建新角色時重用現有的StudentDetails。所以多個課程可以讓同一個學生註冊不同的角色,而不必重複student_details表中的條目。