更改保存其ID的实体的类型 [英] Changing the type of an entity preserving its ID
问题描述
我使用hibernate作为持久层。有两个实体位于同一个表中,用单表继承策略扩展一个超类。
@Entity
@继承(strategy = InheritanceType.SINGLE_TABLE)
公共抽象类A {
@Id
@GeneratedValue
保护长ID;
// B和C $的一些常用字段b $ b}
@实体
公共类B扩展A {
//特定于B的字段
}
@实体
公共类C扩展A {
// C特定字段
}
我有一个id为4的B实例。
B b = em.find(B)如何将此实例的类型更改为C来保存它的ID(4)? .class,4L);
C c = convertToC(b);
c.setId(b.getId());
em.remove(b);
em.persist(c);
上面的代码失败,带有
org.hibernate.PersistentObjectException:传递给persist的分离实体:C
是否有可能?
Hibernate尝试使持久性尽可能透明 - 这意味着它会尝试遵循与普通的Java对象相同的原则。现在,用Java重新编写你的问题,你会得到:
如何将B类的实例转换为(不兼容) )C类?
你知道答案 - 你不能。你可以创建一个C的 new 实例并复制必要的属性,但是B始终是B,而不是C.因此,对原始问题的回答是 - 它不能完成通过JPA或Hibernate API。
然而,与普通Java不同,使用Hibernate可以欺骗:-) InheritanceType.SINGLE_TABLE
使用 @DiscriminatorColumn
进行映射,并且为了将B转换为C,您需要将它的值从B指定的值更新为C指定的值。技巧是 - 您不能使用Hibernate API来做到这一点;你需要通过普通的SQL来完成。但是,您可以将此更新语句映射为命名SQL查询并使用Hibernate工具执行它。
因此,该算法为:
- 从会话中退出 B(这很重要) 执行您的命名查询
- 使用前B的id加载what-is-now-known-as-C。
- 根据需要更新/设置属性。 b $ b
- 坚持C
I am using hibernate as a persistence layer. There are 2 entities that live in the same table extending one superclass with single table inheritance strategy.
@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
}
I have an instance of B with id=4. How do I change the type of this instance to C preserving it's ID (4)?
B b = em.find(B.class, 4L);
C c = convertToC(b);
c.setId(b.getId());
em.remove(b);
em.persist(c);
The code above fails with
org.hibernate.PersistentObjectException: detached entity passed to persist: C
Is it possible at all?
Hibernate attempts to make persistence as transparent as it possibly can - which means it tries to follow the same principles as normal Java objects. Now, rephrasing your question in Java, you'd get:
How can I convert an instance of B class into an instance of (incompatible) C class?
And you know the answer to that - you can't. You can create a new instance of C and copy necessary attributes, but B will always be B, never C. Thus the answer to your original question is - it cannot be done via JPA or Hibernate API.
However, unlike plain Java, with Hibernate you can cheat :-) InheritanceType.SINGLE_TABLE
is mapped using @DiscriminatorColumn
and in order to convert B into C you need to update its value from whatever's specified for B into whatever's specified for C. The trick is - you cannot do it using Hibernate API; you need to do it via plain SQL. You can, however, map this update statement as named SQL query and execute it using Hibernate facilities.
The algorithm, therefore, is:
- Evict B from session if it's there (this is important)
- Execute your named query.
- Load what-is-now-known-as-C using former B's id.
- Update / set attributes as needed.
- Persist C
这篇关于更改保存其ID的实体的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!