我正在使用hibernate作为持久层。存在于同一表中的2个实体通过单表继承策略扩展了一个超类。
@Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) public abstract class A { @Id @GeneratedValue protected Long id; // some common fields for B and C } @Entity public class B extends A { // B-specific fields } @Entity public class C extends A { // C-specific fields }
我有一个ID为4的B实例。如何将此实例的类型更改为C并保留其ID(4)?
B b = em.find(B.class, 4L); C c = convertToC(b); c.setId(b.getId()); em.remove(b); em.persist(c);
上面的代码因
org.hibernate.PersistentObjectException: detached entity passed to persist: C
有可能吗?
Hibernate尝试使持久性尽可能地透明-这意味着它尝试遵循与普通Java对象相同的原则。现在,用Java改写您的问题,您将获得:
如何将B类的实例转换为(不兼容的)C类的实例?
而且您知道答案-您不能。您可以创建C 的 新 实例并复制必要的属性,但B 始终 为B,而不是C。因此,原始问题的答案是- 无法通过JPA或Hibernate API完成。
但是,与普通的Java不同,使用Hibernate可以作弊:-) InheritanceType.SINGLE_TABLE使用映射@DiscriminatorColumn,为了将B转换为C,您需要将其值从B的指定值更新为C的指定值。技巧是- 您无法做到这一点使用Hibernate API;您需要通过普通的SQL来完成。但是,您可以将此更新语句映射为名为SQL查询,并使用Hibernate工具执行它。
InheritanceType.SINGLE_TABLE
@DiscriminatorColumn
因此,该算法为: