Springboot JPA / hibernate:如何映射一个表多个实体

时间:2016-11-19 13:27:24

标签: java spring hibernate jpa spring-boot

我正在创建一个系统,其中有一些实体具有一些常见的属性,如地址(带有街道,数字,拉链等)和电话(数字,类型等),我不想要在每个实体上重复这些列。

这是一个例子:

  • 学生有地址和电话
  • 老师有多个地址(家 和办公室)和多部电话(家庭,移动,办公室)
  • StaffMember 有地址和多个电话(家庭,移动和办公室)

我在使用多态关联开发Ruby On Rails时使用了类似的东西。我在Java / JPA / Hibernate上搜索过类似的东西,找不到类似的东西。我发现了许多关于JPA继承的事情,但我不太了解它。

您能举例说明如何建模以及如何使用它吗?

修改

在阅读我的问题后,我认为还不够清楚,所以让我在这里添加我的数据库架构:

Student
-------
id bigint
name varchar
birth_date date
...

Teacher
-------
id bigint
name varchar
birth_date date
department varchar
...

StaffMember
-------
id bigint
name varchar
birth_date date
department varchar
function varchar
...

Address
-------
id bigint
street varchar
number int
...
entity_id bigint
entity_type varchar

Phone
-----
id bigint
type varchar
number varchar
...
entity_id bigint
entity_type varchar

对于AddressPhoneentity_identity_type列都是对StudentTeacherStaffMember的引用

但是如何使用Hibernate / JPA映射它?

3 个答案:

答案 0 :(得分:1)

如果您不介意使用特定于Hibernate的注释,可以使用@Any@AnyDef注释来执行您想要的操作。您需要为与Address相关的每个实体类型指定一个@MetaValue条目,以便Hibernate知道如何为item_type存储正确的值

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;

import org.hibernate.annotations.Any;
import org.hibernate.annotations.AnyMetaDef;
import org.hibernate.annotations.MetaValue;

@Entity
public class Address {

    @Any(metaColumn = @Column(name = "ITEM_TYPE"))
    @AnyMetaDef(idType = "long", metaType = "string",
            metaValues = {
                    @MetaValue(targetEntity = Student.class, value = "STUDENT"),
                    @MetaValue(targetEntity = Teacher.class, value = "TEACHER")
            })
    @JoinColumn(name="ITEM_ID")
    private Object item;

    @Id
    @GeneratedValue
    private Long id;

    @Column
    private String type;

    @Column
    private String street;

    @Column
    private int number;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }


    public Object getItem() {
        return item;
    }

    public void setItem(Object item) {
        this.item = item;
    }

    @Override
    public String toString() {
        return "Address{" +
                "person=" + item +
                ", id=" + id +
                ", type='" + type + '\'' +
                ", street='" + street + '\'' +
                ", number=" + number +
                '}';
    }
}

现在,您可以在任何具有正确@MetaValue条目的bean中使用Address,这两个条目都是@ManyToOne关联:

@ManyToOne
protected Address address;

或@OneToMany协会:

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
protected Collection<Address> addresses;

我使用Spring Boot创建了一个简单的测试项目,它看起来效果很好!

答案 1 :(得分:0)

我认为您需要的是使用通用存储库类。

这篇文章http://blog.netgloo.com/2014/12/18/handling-entities-inheritance-with-spring-data-jpa解释了它。让我知道是否适合你。

答案 2 :(得分:0)

这些方面的东西:

   @Embeddable
   public class Address {
        // Fields & accessors
        // Do the Phone class in similar fashion
   }

   @Entity
   @DiscriminatorColumn(name = "entity_type")
   public abstract class Person {
        @Id
        private Integer id;

        private String name;

        @Embedded 
        private Address homeAddress;

        @Embedded 
        private Phone homePhone;

       // Other shared fields & accessors

   }

   @Entity
   public abstract class Employee extends Person {

        @Embedded 
        private Phone mobilePhone;

        @Embedded 
        private Phone officePhone;

       //...

    }

    @Entity
    public class Students extends Person {

    }

    @Entity
    public class StaffMember extends Employeee {

    }

    @Entity
    public class Teacher extends Employeee {

      @Embedded
      private Address officeAddress;

      // Accessors & other ...
   }