Hibernate映射多对多非常规方法

时间:2013-07-18 05:16:04

标签: hibernate jpa many-to-many

我们遇到了Java EE JPA映射问题,如下所述:

1)使用的技术是休眠(v ??可能是2.9或更高)和oracle 11G

2)数据库架构师正在实施一个非常常见的数据库结构,类似于以下内容:

    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 个答案:

答案 0 :(得分:0)

忽略JPA,您尝试做的事情在Java中没有意义。如果你的学生去了另一个班级,大概是学生在新班级中的角色可能会有所不同:一个大三学生可能会成为一名大四学生。您不能只使用Java对象切换角色更改 - 您必须创建一个全新的学生实例。正如JB建议的那样,使每个表成为一个实体。然后,您可以使用student_course实体作为包装器来访问Student中适合学生在该课程中的角色的属性。 juniorRole类型只会显示您打算在JuniorStudent中存在的字段。

Role类将使用仅包含OneToOne to course和OneToOne to studentdetails的单表继承,并将该角色用作类型鉴别器。然后,访问器方法将访问studentDetails,当您创建新角色时,它可以重用现有的studentDetails。因此,多个课程可以让同一个学生注册不同的角色,而无需在student_details表中复制条目。