更改保存其ID的实体的类型 [英] Changing the type of an entity preserving its ID

查看:82
本文介绍了更改保存其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工具执行它。



因此,该算法为:


  1. 从会话中退出 B(这很重要) 执行您的命名查询

  2. 使用前B的id加载what-is-now-known-as-C。

  3. 根据需要更新/设置属性。 b $ b
  4. 坚持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:

  1. Evict B from session if it's there (this is important)
  2. Execute your named query.
  3. Load what-is-now-known-as-C using former B's id.
  4. Update / set attributes as needed.
  5. Persist C

这篇关于更改保存其ID的实体的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆