JPA中的继承策略

时间:2017-02-13 07:39:26

标签: java jpa java-ee

我刚接触JPA,所以初学者的问题:

  1. 为什么Hibernate Provider会使用employees_employees创建第二个表? 我的示例中的代码是创建第二个表的原因?

  2. 为什么manager_id列成为员工的id列的fk?为什么我在单表策略中需要fk?

  3. 为什么要创建主键(屏幕截图中的金色)?

  4. 在第二个表employees_employees中创建了department_id作为员工表中的fk到id,为什么?

  5. 来自互联网的任何资源,以便了解这一点,将是HelpFul!

  6. enter image description here

    员工:

    @Entity
    @Table (name = "employees")
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name = "test" , discriminatorType = DiscriminatorType.STRING)
    public class Employee {
    
    public Employee(int id, String name, String lastname, double salary, String spec) {
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.specialization = spec;
        this.lastname = lastname;
    }
    
    public int getId() {
        return id;
    }
    
    public String getName() {
        return name;
    }
    
    public double getSalary() {
        return salary;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void setSalary(double salary) {
        this.salary = salary;
    }
    
    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", salary=" + salary +
                ", spec='" + specialization + '\'' +
                '}';
    }
    
    public String getLastname() {
        return lastname;
    }
    
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }
    
    @Id
    @Column(name = "id")
    private int id;
    
    @Column(name = "name")
    private String name;
    
    @Column(name = "lastname")
    private String lastname;
    
    @Column(name = "salary")
    private double salary;
    
    @Column (name = "specialization")
    private String specialization;
    
    public Manager getManager() {
        return manager;
    }
    
    public void setManager(Manager manager) {
        this.manager = manager;
    }
    
    @OneToOne(cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE}, fetch = FetchType.EAGER)
    private Manager manager;
    
    public Employee(){}
    }
    

    管理器:

    @Entity
    @DiscriminatorValue("M")
    public class Manager extends Employee{
    
    public Manager(){}
    
    
    public Set<Departments> getDepartment() {
        return department;
    }
    
    public void setDepartment(Set<Departments> department) {
        this.department = department;
    }
    
    public String getManager_country() {
        return manager_country;
    }
    
    public void setManager_country(String manager_country) {
        this.manager_country = manager_country;
    }
    
    public String getManager_address() {
        return manager_address;
    }
    
    public void setManager_address(String manager_address) {
        this.manager_address = manager_address;
    }
    
    public String getManager_experience() {
        return manager_experience;
    }
    
    public void setManager_experience(String manager_experience) {
        this.manager_experience = manager_experience;
    }
    
    @Override
    public String toString() {
        return "Manager{" +
                "department=" + department +
                ", manager_address='" + manager_address + '\'' +
                ", manager_experience='" + manager_experience + '\'' +
                ", manager_country='" + manager_country + '\'' +
                ", id=" + id +
                '}';
    }
    
    @OneToMany(fetch = FetchType.EAGER , cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE} )
    private Set<Departments> department;
    
    //private Employee employee;
    
    public Manager(String manager_experience,String manager_address, String manager_country) {
    
        this.manager_experience = manager_experience;
        this.manager_address = manager_address;
        this.manager_country = manager_country;
    }
    
    @Column(name = "experience")
    private String manager_experience;
    
    @Column(name = "address")
    private String manager_address;
    
    @Column(name = "country")
    private String manager_country;
    
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "manager_id" ,insertable = false , updatable = false)
    private int id;
    }
    

    部门:

    @Entity
    @DiscriminatorValue("D")
    public class Departments extends Manager{
    
    public String getSales() {
        return sales;
    }
    
    public void setSales(String sales) {
        this.sales = sales;
    }
    
    public String getCostumer_support() {
        return costumer_support;
    }
    
    public void setCostumer_support(String costumer_support) {
        this.costumer_support = costumer_support;
    }
    
    public String getDevelopers() {
        return developers;
    }
    
    public void setDevelopers(String developers) {
        this.developers = developers;
    }
    
    public String getSystem_administrators() {
        return system_administrators;
    }
    
    public void setSystem_administrators(String system_administrators) {
        this.system_administrators = system_administrators;
    }
    
    public String getAccounting_department() {
        return accounting_department;
    }
    
    public void setAccounting_department(String accounting_department) {
        this.accounting_department = accounting_department;
    }
    
    //private Manager manager;
    
    @Column(name = "costumer_support_department" , unique = false, updatable = true , insertable = true , nullable = true)
    private String costumer_support;
    
    @Column(name = "developers_department" , unique = false, updatable = true , insertable = true , nullable = true)
    private String developers;
    
    @Column(name = "sys_admins_department" , unique = false, updatable = true , insertable = true , nullable = true)
    private String system_administrators;
    
    @Column(name = "accounting_department" , unique = false, updatable = true , insertable = true , nullable = true)
    private String accounting_department;
    
    @Column(name = "sales_department" , unique = false, updatable = true , insertable = true , nullable = true)
    private String sales;
    
    public Departments(){}
    }
    

2 个答案:

答案 0 :(得分:1)

由于您已选择SINGLE_TABLE作为继承策略,因此EmployeeManager都存储在同一个表中。

  1. 默认情况下,单向一对多关系(在您的情况下为Employee.manager)由JPA在附加联接表的帮助下表示(就像多对多关系一样)。在您的情况下,它恰好加入employees表自己。如果您想在源实体表中使用外键,则需要使用@JoinColumn

  2. 这与第1点有关。你能用下面的代码解释一下你想要完成的事吗? Manager已经有一个id(来自其父实体)

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "manager_id" ,insertable = false , updatable = false)
    private int id;
    
  3. 如果您切换到使用@JoinTable的事件,employees表格中仍会有外键(您认为Employee - Manager关系怎么样?在数据库中表示?)

    1. 由于以下代码:

      @Id
      @Column(name = "id")
      private int id;
      
    2. 好问题。我认为这是因为Department是一个Manager,当Employee.manager实际指向Department时,JPA需要这种方式。为什么要让Department继承ManagerDepartment有一个Manager@OneToOne/@ManyToOne)更合乎逻辑吗?这会简化事情,你知道

    3. https://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Example_of_a_OneToMany_using_a_JoinTable_database https://en.wikibooks.org/wiki/Java_Persistence/Inheritance(这些确实是Google的最佳结果......)
    4. 修改

      要实施Department has-a Manager关系,您需要进行以下更改:

          @Entity
          public class Department {
              @Id
              private int id;
      
              @ManyToOne(mappedBy = "department")
              private Manager manager;
              ...
          }
      

      Department.manager并非绝对必要,但我已将其包含在内,以防您想要双向关系(我没有注意到Manager.department字段已经在{ {1}}我第一次读你的代码时)

答案 1 :(得分:0)

不确定你想要实现的目标。但肯定你的代码看起来有点奇怪。

1)表employees_employees已经创建,因为您已经提到管理器和部门之间的映射为一对多。一个表策略默认为一对一映射。

2)问题是你有2个同名id的变量;一个在employee表中,另一个在manager表中。

3)是正确的行为。您在员工类中使用了@id注释。因此创建了主键。

4)因为你使用了单表策略。部门的超级父级是员工,因此部门的主要关键栏与员工的主要关键栏相同。所以department_id引用了employee表的id。

5)告诉我们您想要达到的目标,我们可以为您提供帮助。或者浏览一下hibernate教程。