How Hibernate distincts object type with InheritanceType.JOINED

时间:2019-03-19 15:17:57

标签: java hibernate jpa spring-data-jpa

I have different user types in my Spring app. I implemented some kind of Inheritance. All users types extends from User class. I think two tables should be enough here:

  1. table "users" - contains columns for all shared entity attributes
  2. table "users_corporate" - contains columns for CorporateCustomer class attriburtes: companyName and VatNumber

"users" will have: id, username, password, first_name, last_name, email, mobile, city, street, postcode

"users_corporate" will have: company_name, vat_number

Class RetailCustomer and Provider doesn't have any fields with @Column annotation so there is no need to have table for them, I only need to declare fields with OneToMany mappings.. Now I'm wondering how hibernate will distinct Provider and RetailCustomer from each other if I don't have @Table annotation in their class. When I will use Spring Data repository and for example call providerRepository.findAll() how it will now which rows from "users" table are provider and which are retailCustomer? Will it work? Am I missing something?

BaseEntity:

@MappedSuperclass
public class BaseEntity{

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

User:

@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;

}

CorporateCustomer:

@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;
}

RetailCustomer:

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

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

Provider:

@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;
}

1 个答案:

答案 0 :(得分:0)

  

冬眠如何将Provider和RetailCustomer与众不同   其他如果我的班级没有@Table注释?

如果您未使用@Table指定表名,则表的名称将与实体名称相同。

  

当我调用providerRepository.findAll()时,它将如何从   “用户”   表是提供者,哪些是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_帮助器列区分将创建哪个实体类。