首页 > 解决方案 > Hibernate 如何使用 InheritanceType.JOINED 区分对象类型

问题描述

我的 Spring 应用程序中有不同的用户类型。我实现了某种继承。所有用户类型都从用户类扩展。我认为这里有两张表就足够了:

  1. 表“用户” - 包含所有共享实体属性的列
  2. 表“users_corporate” - 包含 CorporateCustomer 类属性的列:companyName 和 VatNumber

“用户”将有:id、用户名、密码、名字、姓氏、电子邮件、手机、城市、街道、邮政编码

“users_corporate”将有:company_name、vat_number

类 RetailCustomer 和 Provider 没有任何带有 @Column 注释的字段,因此不需要为它们提供表,我只需要声明带有 OneToMany 映射的字段。现在我想知道 hibernate 将如何区分 Provider 和 RetailCustomer其他如果我在他们的班级中没有@Table 注释。当我将使用 Spring Data 存储库并例如调用 providerRepository.findAll() 时,它现在将如何将“用户”表中的哪些行是提供者,哪些是零售客户?它会起作用吗?我错过了什么吗?

基本实体:

@MappedSuperclass
public class BaseEntity{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
}

用户:

@Entity
@Table(name="users")
@Inheritance(strategy = InheritanceType.JOINED)
public class User extends BaseEntity{

    @Column(name = "username")
    private String userName;

    @Column(name = "password")
    private String password;

    @Column(name = "email")
    private String email;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Collection<Role> roles;

}

企业客户:

@Entity
@Table(name="users_corporate")
public class CorporateCustomer extends User{

    @Column(name = "company_name")
    private String companyName;

    @Column(name = "vat_number")
    private String vatNumber;

    @OneToMany(mappedBy = "customer")
    private List<Appointment> appointments;
}

零售客户:

@Entity
//@Table  <---- i think it is not needed here?
public class RetailCustomer extends User {

    @OneToMany(mappedBy = "customer")
    private List<Appointment> appointments;
}

提供者:

@Entity
//@Table  <---- i think it is not needed here?
public class Provider extends User{

    @OneToMany(mappedBy = "provider")
    private List<Appointment> appointments;

    @ManyToMany
    @JoinTable(name="works_providers", joinColumns=@JoinColumn(name="id_user"), inverseJoinColumns=@JoinColumn(name="id_work"))
    private List<Work> works;

    @OneToOne(mappedBy="provider", cascade = {CascadeType.ALL})
    private WorkingPlan workingPlan;
}

标签: javahibernatejpaspring-data-jpa

解决方案


如果我的类中没有 @Table 注释,休眠将如何区分 Provider 和 RetailCustomer?

如果不使用@Table 指定表名,则表名与实体名相同。

当我调用providerRepository.findAll() 时,“users”表中的哪些行是provider,哪些是retailCustomer?

如果从 ProviderRepository 中选择,则休眠生成inner join. 只会返回提供者实体。Hibernate 生成原生 SQL:

select ... from Provider p
inner join User u on p.id=u.id

对于使用 UserRepository 选择所有用户,休眠将生成left join. 结果将包含所有可能的用户类型。Hibernate 生成原生 SQL:

select ..., 
case 
when r.id is not null then 1 
when p.id is not null then 2 
when u.id is not null then 0 
end as clazz_0_ 
from User u
left outer join Provider p on p.id=u.id 
left outer join RetailCustomer r on r.id=u.id

clazz_0_帮助列区分将创建哪个实体类。


推荐阅读