3

我想知道如果实体不共享主键,那么在 JPA 实体中使用继承的最佳做法是什么,特别是如果数据库已经存在并且不能轻易更改。

假设我们有一个员工数据库,就像Oracle HR 示例中使用的那样。现在,该数据库不太现实。工资通常会随着时间而变化,我们将跟踪工资的变化情况。例如,一份工作合同可能会规定,每年 12 月,员工都会与他们的经理会面,讨论下一年的工资。

因此,我们将从 HR.EMPLOYEES 中删除薪水字段并创建一个新表 HR.SALARIES:

EMPLOYEE_ID NOT NULL NUMBER(6)
VALID_FROM NOT NULL DATE
SALARY NUMBER(8,2)

主键将由 EMPLOYEE_ID 和 VALID_FROM 组成。

因此,现在如果 Pat 在 12 月遇到她的经理 Michael 并同意新的薪水,我们将在 HR.SALARIES 中插入一条新记录。

现在,让我们假设 HR 部门在输入新数据时出错,因此 Pat 在 1 月份得到了错误的薪水。她将问题报告给她的老板,他联系人力资源部门,他们更正了 HR.SALARIES 中的记录。她将在 2 月份的付款中收到缺失的金额。

年底,公司进行审计。审计员想知道为什么 1 月份发给 Pat 的工资支票与数据库中的工资条目不匹配。为了确保审计人员始终能够理解系统做出某些决定的原因(例如开出一定数量的支票),我们需要保留更改历史记录。

将 HR.SALARIES 更改为:

EMPLOYEE_ID NOT NULL NUMBER(6)
VALID_FROM NOT NULL DATE
SALARY NUMBER(8,2)
CHANGE_DATE NOT NULL DATE

添加新表 HR.SALARIES_CHANGE_HISTORY:

EMPLOYEE_ID NOT NULL NUMBER(6)
VALID_FROM NOT NULL DATE
SALARY NUMBER(8,2)
CHANGE_DATE NOT NULL DATE

主键将由 EMPLOYEE_ID、VALID_FROM 和 CHANGE_DATE 组成。

出于性能原因,我们将更改历史记录保存在单独的表中:我们的 HR 系统几乎不会读取它。

现在我们终于来回答我的问题了。我们如何在 JPA 中最好地为这个数据库建模,我们能否以某种方式利用继承,因为表 HR.SALARIES 和 HR.SALARIES_CHANGE_HISTORY 是相同的,除了 CHANGE_DATE 是 HR.SALARIES_CHANGE_HISTORY 中主键的一部分。

JavaEE 中有 @MappedSuperclass,一开始听起来不错,但在使用 @MappedSupperclass 的类层次结构中不可能使用不同的主键(请参阅JSR-000338 JavaTM Persistence 2.1,第 2.4 节JSR 220:Enterprise JavaBeansTM,版本3.0,第 2.1.4 节)。

有什么方法可以避免 SALARIES 和 SALARIES_CHANGE_HISTORY 的实体 bean 中的代码重复?

4

0 回答 0