java - JPA向下转型以访问子类方法

标签 java jakarta-ee jpa persistence downcast

数据库表:

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/

相关文章:

spring - Spring框架有自己的bean吗?

java - 定时运行任务java,apache

java - 如何使用 JPA 和 Hibernate 将 MySQL JSON 列映射到 Java 实体属性

java - mmap() vs Java MappedByteBuffer 性能?

Java Map,其中值是与键类型相同的值列表

java - 使用 Java 管理非常长时间的操作

java - JPA : Many to Many query help needed

java - 在类层次结构中使用注入(inject)的 EntityManager

java - Jetty:隐藏 URL 中的端口号

java - 检测 GitHub 存储库中的语言