java - 如何使用 Hibernate 将 ORM 转换为其子类?

标签 java hibernate orm inheritance

例如,我有两个类: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/

相关文章:

java - Java 中使用 XADES-EPES 进行 XML 签名有一个很好的示例吗?

Mysql 连接器无法创建具有复合主键的表

java - JPA - 在 Postgresql 上保留 LOB 属性

php - 跨数据库连接学说

sql - 使用 ORM 进行大容量数据库更新

Java javax.swing.Timer 在新线程上运行吗?

java - 如何使用java从Mongodb集合中检索数组列表的元素?

java - 从 HashMap 中获取具有最大值的键?

java - SQL查询: incorrect work with entity

java - 为什么在Spring-Hibernate Configuration中同时配置dataSource和sessionFactory?