【问题标题】:How Hibernate distincts object type with InheritanceType.JOINEDHibernate 如何使用 InheritanceType.JOINED 区分对象类型
【发布时间】:2019-08-10 04:18:40
【问题描述】:

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

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

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

“users_corporate”将有:company_name、vat_number

类 RetailCustomer 和 Provider 没有任何带有 @Column 注释的字段,因此不需要为它们提供表,我只需要声明带有 OneToMany 映射的字段.. 现在我想知道如果我的类中没有 @Table 注释,休眠将如何区分 Provider 和 RetailCustomer 。当我将使用 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;
}

【问题讨论】:

    标签: java hibernate jpa spring-data-jpa


    【解决方案1】:

    hibernate 如何区分 Provider 和 RetailCustomer 如果我在他们的班级中没有@Table 注释,是否还有其他?

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

    当我调用 providerRepository.findAll() 时,它现在将如何从哪些行 “用户” 表是供应商,哪些是零售客户?

    如果从 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_ helper 列区分将创建哪个实体类。

    【讨论】:

    • 谢谢,在这种情况下我会有 4 张桌子。但我不明白的是,我不知道实体 Provider 和 RetailCustomer 的表应该是什么样子。这些实体没有新列,提供者的所有数据都已存储在“用户”表中。 RetailCustomer 也是如此。只有 CorpotateCustomer 有新的、不常见的附加字段。
    • 它将只包含 ID 列
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-30
    • 2021-03-26
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 1970-01-01
    相关资源
    最近更新 更多