Changing the type of an entity preserving its ID
hibernate, java, persistence
Solution
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
Problem
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?