数据库表:
Employee Table
ID, Type, Salary, Rate
类型可以是全职或契约(Contract)工。 full time 具有 salary 属性,contractor 具有 rate 属性。 (我知道它没有标准化。但它就是这样。如果你能告诉我为什么它是一个糟糕的设计,我将不胜感激)
JPA 类:(甲骨文 JPA)
@Entity
@Table(name="Employee")
public abstract class Employee{...}
@Entity
public class FullTimeEmployee extends Employee{...}
public class EmployeeService{
...
Employee joe = entityManager.find(Employee.class, id);
((FullTimeEmployee) joe).getSalary(); //Can I do this?
//Or I have to use Employee joe = entityManager.find(FullTimeEmployee.class, id);
...
}
我可以用这种方式向下转换实体类吗?谢谢!
编辑:
我的其他担忧是这样的。两种类型的员工都存储在同一个表中。那么 entityManager.find(Employee.class, id) 怎么知道哪个 id 是全职的呢?
那么,如果我这样做了会有什么不同吗
entityManager.persist((Employee)fullTimeEmp);
代替
entityManager.persist(fullTimeEmp);
最佳答案
Can I downcast a entity class this way?
你可以,而且它会起作用,但并非总是如此。所以我不会这样做。例如,如果你有一个与雇员的惰性 toOne 关联,或者如果你碰巧在之前的同一个 session 中使用 em.getReference() 来“加载”该雇员,你将得到一个 ClassCastException,因为 Hibernate 将返回一个代理到员工,既不是全职员工也不是承包商。
如果您避免使用 instanceof
和强制转换,而是使用多态性,那么您是安全的。例如,您可以在基类中定义一个抽象的 getSalary()
方法,并在子类中提供不同的实现。或者您可以使用访问者模式。
Both 2 types of employee was stored in the same table. So how come entityManager.find(Employee.class, id)
它知道,因为您必须有一个鉴别器列,其中包含实体的类型。从数据库加载行时,Hibernate 从该列读取类型并实例化适当的子类。
So, does it make a difference if I did
entityManager.persist((Employee)fullTimeEmp);
不,一点也不。 fullTimeEmp
的实际具体类型是 FullTimeEmployee,无论您是否将其转换为 Employee,这就是 Hibernate 用来了解必须如何保存员工(在这种情况下,它必须将哪个值存储在鉴别器列)。
关于java - JPA向下转型以访问子类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32956520/