数据库表:
Employee Table
ID, Type, Salary, Rate
类型可以是全职或承包商。而全职工资的属性,承包商有费率的属性。 (我知道它没有正常化。但它就是它。如果你能教育我为什么这是一个糟糕的设计,那就感激不尽了)
JPA课程:(Oracle 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);
答案 0 :(得分:1)
我可以用这种方式转发实体类吗?
你可以,它会起作用,但并不总是如此。所以我不会这样做。例如,如果您与员工有一个懒惰的toOne关联,或者您碰巧使用了em.getReference()来加载"在之前的同一会话中,您将获得ClassCastException,因为Hibernate将向Employee返回一个代理,既不是FullTimeEmployee也不是Contractor。
如果你避免使用instanceof
并进行强制转换,并且使用多态性,那么你是安全的。例如,您可以在基类中定义抽象getSalary()
方法,并在子类中提供不同的实现。或者你可以使用访客模式。
两种类型的员工都存储在同一个表中。那么如何实现entityManager.find(Employee.class,id)
它知道,因为你必须有一个鉴别器列,包含实体的类型。从数据库加载行时,Hibernate从该列读取类型并实例化相应的子类。
那么,如果我这样做会有所作为吗
entityManager.persist((Employee)fullTimeEmp);
不,一点也不。 fullTimeEmp
的实际具体类型是FullTimeEmployee,无论您是否将其转换为Employee,以及Hibernate用于了解必须如何保存员工的内容(在这种情况下,它必须存储在哪个值中)鉴别器栏目。)
答案 1 :(得分:0)
由于您没有显式设置继承映射的策略,因此默认值为InheritanceType.SINGLE_TABLE。这意味着,所有持久化实体(无论持久化具体的子类类型)都将存储在单个表中。如果使用单个表,您很可能会有一个鉴别器列,它将区分应该是哪个子类类型的特定行。 这是一个很好的example。
关于如何查询特定子类型的问题,您可以使用JP QL关键字TYPE。
示例:
SELECT e FROM Employee e WHERE TYPE(e) = FullTimeEmployee
此查询的结果将是所有FullTimeEmployee对象。
此外,如果您正在寻找给定ID的特定FullTimeEmployee对象。以下代码也是可能的:
em.find(FullTimeEmployee.class, id);