Java Springboot JPA/hibernate:如何将一个表映射到多个实体
我正在创建一个系统,在这个系统中,我有一些实体,它们有一些公共属性,比如地址(带有街道、号码、邮编等)和电话(号码、类型等),我不想在每个实体上重复这些列 这里有一个例子:Java Springboot JPA/hibernate:如何将一个表映射到多个实体,java,spring,hibernate,jpa,spring-boot,Java,Spring,Hibernate,Jpa,Spring Boot,我正在创建一个系统,在这个系统中,我有一些实体,它们有一些公共属性,比如地址(带有街道、号码、邮编等)和电话(号码、类型等),我不想在每个实体上重复这些列 这里有一个例子: 学生有地址和电话 老师有多个地址(家) 和办公室)和多部电话(家庭、手机、办公室) 员工 有地址和多部电话(家庭、手机和办公室) 我在使用多态关联开发RubyonRails时使用过类似的东西。我在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
对于地址
和电话
,列实体id
和实体类型
都是对学生
、教师
和员工
的引用
但是如何使用Hibernate/JPA映射它呢?我认为您需要的是使用一个通用的存储库类
这篇文章解释了很多。请告诉我是否适合您。以下内容:
@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 ...
}
如果您不介意使用特定于Hibernate的注释,那么可以使用和注释来实现您想要的功能。您需要为每个与地址相关的实体类型指定一个条目,以便Hibernate知道如何存储项类型的正确值
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(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
protected Collection<Address> addresses;
或@OneToMany协会:
@ManyToOne
protected Address address;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
protected Collection<Address> addresses;
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
受保护的收集地址;
我使用SpringBoot创建了一个简单的测试项目,它似乎工作得很好 请确定:您的数据库模式是固定的,JPA/hibernate必须对其进行调整吗?Hi@larsgrefer,不,该模式足够灵活,上面只是一个它认为最好的示例,但我愿意接受建议。当您使用spring boot时,只需设置
spring.jpa.generate ddl=true
,让hibernate为youHi@Nicolas Fontenele生成模式,这并不是我想要的(或者我解释错了)。我已经在我的问题中添加了更多的细节,所以它可能会帮助您更好地理解。无论如何,谢谢。Hi@dev null通过使用嵌入式,我可以将地址存储在单独的表中吗?我不想在数据库中的每个表上复制这个结构,@embeddeble的要点是它没有特殊的表,只是嵌入到其他表中的数据结构。类似复合数据类型的东西。谢谢@João Marcus,这正是我想要的!请解释“.它有正确的@MetaValue条目”。通过这种方式,我得到了从学生
到地址
的单向@OneToMany
关系,由于缺少无法定义的mappedBy
属性,它创建了一个额外的学生地址
,教师地址
表。我怎样才能避免呢?