例如,我有两个类:Person 和 Employee(Employee 是 Person 的子类)。 Person :有姓氏和名字。 员工:也有薪水。
在客户端,我有一个 HTML 表单,我可以在其中填写人员信息(如姓氏和名字)。我在“人”和“雇员”之间也有一个“开关”,如果开关在雇员上,我可以填写工资字段。
在服务器端,Servlet 从客户端接收信息并使用 Hibernate 框架创建/更新数据库中的数据。我使用的映射是个人和雇员的单个表,带有鉴别器。
我不知道如何将 Person
转换为 Employee
,方法是修改其用作 的
.type
>DiscriminatorColumn
我首先尝试:
- 从数据库中加载人物 p
- 创建一个空的 Employee e 对象
- 将值从 p 复制到 e
- 设置工资值
- 将e存入数据库
但我不能,因为我还复制了 ID,所以 Hibernate 告诉我他们在哪里有两个具有相同 ID 的实例化 ORM。
而且我不能直接将 Person 转换为 Employee,因为 Person 是 Employee 的父类(super class)。
似乎有一种肮脏的方式:删除这个人,然后用相同的信息创建一个员工,但我不太喜欢它..
所以我很感激任何帮助:)
一些精度:
人物类:
public class Person {
protected int id;
protected String firstName;
protected String lastName;
// usual getters and setters
}
员工类:
public class Employee extends Person {
// string for now
protected String salary;
// usual getters and setters
}
在 servlet 中:
// type is the "switch"
if(request.getParameter("type").equals("Employee")) {
Employee employee = daoPerson.getEmployee(Integer.valueOf(request.getParameter("ID")));
modifyPerson(employee, request);
employee.setSalary(request.getParameter("salary"));
daoPerson.save(employee );
}
else {
Person person = daoPerson.getPerson(Integer.valueOf(request.getParameter("ID")));
modifyPerson(employee, request);
daoPerson.save(person);
}
最后,加载(在 dao 中):
public Contact getPerson(int ID){
Session session = HibernateSessionFactory.getSession();
Person p = (Person) session.load(Person.class, new Integer(ID));
return p;
}
public Contact getEmployee(int ID){
Session session = HibernateSessionFactory.getSession();
Employee = (Employee) session.load(Employee.class, new Integer(ID));
return p;
}
有了这个,我在尝试使用 getEmployee 加载 Person 时遇到了 ClassCastException。
XML hibernate 映射:
<class name="domain.Person" table="PERSON" discriminator-value="P">
<id name="id" type="int">
<column name="ID" />
<generator class="native" />
</id>
<discriminator column="type" type="character"/>
<property name="firstName" type="java.lang.String">
<column name="FIRSTNAME" />
</property>
<property name="lastName" type="java.lang.String">
<column name="LASTNAME" />
</property>
<subclass name="domain.Employee" discriminator-value="E">
<property name="salary" column="SALARY" type="java.lang.String" />
</subclass>
</class>
够清楚了吗? :-/
最佳答案
几年前,当我进行审查时,我发现了一个可以解决您的问题的bad bad hack。
如果我对您的理解是正确的——您需要将 Person 转换为 Employee 并返回。 他们使用了一个鉴别器列,我们称它为“disc”,并假设您使用一个字符串鉴别器,其中包含两个值 PERSON 和 EMPLOYEE。然后你需要一个额外的列来将鉴别器列映射到你的 Person 类。我们称它为“hackType”。
@Column(columnName=”disc”)
private String hackType;
现在您已经耦合了 hackType 和对象的类型。首先,您需要确保 hackType 对所有人员都是 PERSON,对所有员工都是 EMPLOYEE。 – 但是如果你想将一个Person“转移”到一个Employee,你只需要加载Person(通过ID),将它的字段hackType设置为EMPLOYEE,保存,清除缓存,然后重新加载(通过ID)作为一个员工。
但这是一个非常糟糕的 hack,我已经在 nHibernate 上看到过它,但我认为它也可以用于 (Java) Hibernate。 – 无论如何,我强烈建议不要以这种方式进行,但是了解这个 hack 很有趣。
至少我认为问题在于您的域模型是错误的:Employee 不应该是 Person 的子类。因为这意味着 Employee 将始终是 Employee,而 Person (如果它被创建为一个人)将永远不会成为一个雇员。我强烈建议在 Person 和 Employee 之间建立 1:1 的关系。其中 Person 是主要对象,而 Employee 是 Person 的可选扩展。 (在这种情况下,您需要将 Employee 重命名为类似 EmploymentFacts 的名称,以表明这只是一个人的 Employee 部分。)
关于java - 如何使用 Hibernate 将 ORM 转换为其子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4711870/