Hibernate 的行为 get vs load with discriminator

Behavior of Hibernate get vs load with discriminator

我想知道为什么 hibernate 的“获取”和“加载”行为对于受歧视的实体有不同的表现?

映射:

@Entity
@Table(name = "person")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "type")
public abstract class BasePerson {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    protected Integer id;

    @Column(name = "name")
    private String name;
    ...
@Entity
@DiscriminatorValue("COMPANY")
public class Company extends BasePerson {

    ...
@Entity
@DiscriminatorValue("CITIZEN")
public class Citizen extends BasePerson {

    ...

以下调用 returns 特定子实体(公司或公民):

(BasePerson) hibernateTemplate.getSessionFactory().getCurrentSession().get(BasePerson.class, id);

下面只调用returns超级实体BasePerson:

(BasePerson) hibernateTemplate.getSessionFactory().getCurrentSession().load(BasePerson.class, id);

为什么会这样?我如何使用 load() 但获得具体实现(Citizen 或 Company 对象)?

这是因为 load() 不会触发 SELECT 语句。它只是为您使用您传递的 ID 传递的 class 创建一个代理。稍后当您在该代理上调用方法时 - Hibernate 将从 DB 获取 SELECT 数据。但那时它无法更改已存在对象的 class,因此在这种情况下,您将始终使用超级 class。

在实践中,如果您在实体中的某处引用具有惰性 OTM 或 OTO 关系的层次结构的超级 class,通常会发生这种情况。由于该字段是惰性的,ORM 还将创建它知道的任何 class 的代理(在这种情况下它是超级 class)。

PS:load() 可以 return 一个实体而不是代理,但前提是该实体已经被其他代码加载并且它已经驻留在会话中。