我们遇到了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正在努力理解我们要求的内容。如果可能,我们更喜欢使用注释配置。
答案 0 :(得分:0)
忽略JPA,您尝试做的事情在Java中没有意义。如果你的学生去了另一个班级,大概是学生在新班级中的角色可能会有所不同:一个大三学生可能会成为一名大四学生。您不能只使用Java对象切换角色更改 - 您必须创建一个全新的学生实例。正如JB建议的那样,使每个表成为一个实体。然后,您可以使用student_course实体作为包装器来访问Student中适合学生在该课程中的角色的属性。 juniorRole类型只会显示您打算在JuniorStudent中存在的字段。
Role类将使用仅包含OneToOne to course和OneToOne to studentdetails的单表继承,并将该角色用作类型鉴别器。然后,访问器方法将访问studentDetails,当您创建新角色时,它可以重用现有的studentDetails。因此,多个课程可以让同一个学生注册不同的角色,而无需在student_details表中复制条目。