Java Hibernate:将基类的实例更改为子类

Java Hibernate:将基类的实例更改为子类,java,hibernate,jpa,Java,Hibernate,Jpa,我想将一个具体的超类更改为它的一个子类。我在下面举了一个例子: @Entity @Table(name = "employees") @Inheritance(strategy = InheritanceType.JOINED) public class Employee { @Id @Column(name = "id") private String id; public Employee( String id ) { this.id =

我想将一个具体的超类更改为它的一个子类。我在下面举了一个例子:

@Entity
@Table(name = "employees")
@Inheritance(strategy = InheritanceType.JOINED)
public class Employee {

    @Id
    @Column(name = "id")
    private String id;

    public Employee( String id ) {
        this.id = id;
    }
 ...
}

@Entity
@Table(name = "managers")
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
public class Manager extends Employee {

    public Manager( String id ) {
        super(id);
    }
 ...
}


@Entity
@Table(name = "history")
public class History {
 ...
/**
 * 
 */
@ManyToOne
@JoinColumn(name = "employee_id")
private Employee employee;
 ...
}
我工作的三个班级是雇员、经理和历史。所有经理都是员工,但并非所有员工都是经理。所有员工(和经理)都有历史记录。员工可能被提升为管理层。发生这种情况时,应通过保持员工ID不变来保留员工的历史记录。这样可以很容易地找到经理的雇佣历史

实现升级操作由于数据库的限制而变得复杂:如果不通过级联操作删除所有历史对象,数据库将不允许删除旧员工并创建具有相同ID的新经理,这是人力资源不允许的,否则我的工作将很容易

是否可以在不使用自定义SQL操作的情况下将经理(新经理)行添加或附加到现有员工

我尝试了以下解决方案,但没有成功:

public void promote( Employee employee ) {
    /* copy over the ID of the employee to the manager.  Will not work because employee with ID already exists */
    Manager manager = new Manager(employee.getId());
    this.entityManager.persist( manager );
}
。。。或者

public void promote( Employee employee ) {
    /* detach the employee then merge.  Will not work: fails, again, with a NonUniqueObject Exception */
    this.entityManager.detach( employee );
    Manager manager = new Manager(employee.getId());
    this.entityManager.merge( manager );
}
我怎样才能做到这一点?我使用detach()和merge()的方法是否正确

这在Hibernate/JPA中可能吗

在这一点上,任何想法都会有帮助,因为我被难住了

  • 亚伦

    • 毫无疑问,你开始看到,你在逆风划船。不幸的是,看起来你有一个典型的例子。Hibernate(一种对象关系映射器)和Java(一种面向对象的语言)都将在这一点上与您发生冲突,因为您的对象模型是错误的。我认为最好的办法是现在就通过重构和数据迁移来修复它。最终的结果应该是每个人都是一名员工,有些员工与一个或多个部门或其他员工有某种“管理”关系。

      我遇到了类似的情况,我不认为有缺陷的数据模型是罪魁祸首,因为数据模型与现实世界的模型非常匹配

      您可以手动插入子类记录以获得所需的结果。有时需要绕过Hibernate来完成一些事情,所以我在本例中就是这样做的:

      sessionFactory.getCurrentSession().createSQLQuery(
                  "insert into manager (employee_id, rank) " +
                  "values (:employeeId, :rank) ")
                  .setParameter("employeeId", employeeId)
                  .setParameter("rank", rank)
                  .executeUpdate();
      

      Hibernate是否有一种在Hibernate中处理这种常见OO错误的方法?这个问题也可以被描述为一个对象标识问题:我希望能够告诉Hibenate,对于一个事务,忘记试图保留.equals()和==语义集-让我让对象不相等,!=,,指示它为子类执行插入操作。我知道这会让持久性VM状态变得有些不一致——应用程序实际上就是为此而设计的(没有缓存等等)。还有其他想法吗?@Aaron:你有映射的员工->历史关系吗?如果是这样,您应该能够创建一个Manager对象,将旧员工的所有属性复制到新经理,然后在经理的历史记录中设置History对象,并将员工的历史记录设置为null,从而实质上将历史记录的所有权从Employee实例转移到Manager实例。谢谢!是的,这似乎是我需要做的(或类似的:()。最初我认为低级别的hibernate/jpa方法之一有助于管理身份的变化,但它不起作用。