我想将一个具体的超类更改为其子类之一。我在下面列举了一个例子:
@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相同来保留员工的历史记录。这样可以轻松找到经理人的就业历史。
实施促销操作因数据库的约束而变得复杂:数据库不允许删除旧的Employee并创建具有相同ID的新Manager而不通过级联操作删除所有History对象 - 人力资源部门不会允许,否则我的工作会很容易!
是否可以将或附加管理器(新管理员)行添加到现有员工而无需借助自定义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中是否可行?
在这一点上任何想法都会有所帮助,因为我很难过!
答案 0 :(得分:6)
正如你无疑开始看到的那样,你在风中划风。不幸的是,看起来你有using inheritance to represent role的典型例子。 Hibernate - 一个 Object - 关系映射器 - 和Java - 面向 Object 的语言 - 都会在这个问题上打击你,因为你的对象模型是错误的。我想说你最好的办法是通过重构和数据迁移来解决它。最终结果应该是每个人都是员工,而一些员工与一个或多个部门或其他员工之间存在某种“管理”关系。
答案 1 :(得分:1)
我遇到了类似的情况,我不相信有缺陷的数据模型是错误的,因为数据模型很好地匹配了现实世界的模型。
您可以手动插入子类记录以获得所需的结果。有时候绕过Hibernate来完成某些事情是必不可少的,所以这就是我在这种情况下所做的解决方法:
sessionFactory.getCurrentSession().createSQLQuery(
"insert into manager (employee_id, rank) " +
"values (:employeeId, :rank) ")
.setParameter("employeeId", employeeId)
.setParameter("rank", rank)
.executeUpdate();