Hibernate入门(5):关联映射&继承映射
2017-09-07 22:33
447 查看
关联映射
1、除了关系型数据库本身提供的基于关系的关联映射,Hibernate 也提供了面向对象的关联映射支持,这些关联关系大大简化了持久层数据的访问;2、Hibernate提供的关联关系可以分为以下2种,可以根据需求选择关联形式;单向关联:只能从一端访问另一端;双向关联:两端都可以相互访问;3、单向关联包含以下4种关系:1-1(一对一),1-N(一对多),N-1(多对一),N-N(多对多); 4、双向关联包含以下3种关系(双向关联中1-N,N-1完全相同):1-1,1-N,N-N;
5、对于这些关联关系,hibernate 提供了以下4个注解支持:@OneToOne:1-1关系@OneToMore:1-N关系@MoreToOne:N-1关系@MoreToMore:N-N关系这些注解支持的常用属性如下:
cascade | 指定对于关联主体的级联策略,不设置时,不启用级联,可选值如下: CascadeType.ALL:将所有的持久化操作级联到关联实体; CascadeType.MERGE:将merge操作级联到关联实体; CascadeType.PRESIST :将presist操作级联到关联实体; CascadeType.REFRESH 4000 :将refresh操作级联到关联实体; CascadeType.REMOVE :将remove操作级联到关联实体; |
fetch | 指定抓取关联实体的策略,可选值如下: FetchType.EAGER:立即抓取 FetchType.:LAZY:延迟抓取(默认值) |
mappedBy | 指定关联实体中那个属性值可以被引用到当前实体,值为关联实体的某个属性名; 当@OneToMany @ManyToMany 指定了该属性后,表明当前实体不能控制关联关系; 当某一段使用mappedBy放弃控制权后,该一段不能使用@JoinColumn,@JoinTable |
orphanRemoval | 设置是否删除“孤儿”实体,如果某个实体所关联的父实体不存在,该实体为孤儿实体 |
tragetEntity | 该属性关联实体的类名,默认情况下 hibernate 会通过反射来判断关联实体的类名 |
7、Hibernate 支持有连接表和无连接表的关联映射;无连接表时,需要使用 @JoinColumn ,来映射外键列,支持属性如下:
name | 指定外键列列名 |
columnDefinition | 使用指定的SQL片段创建外键列 |
nullable | 指定该列是否允许为null,默认值 true |
table | 指定该列的所在数据表的表名 |
unique | 指定是否为该列增加唯一约束,默认值 false |
referenceColumnName | 指定所参照的主键列的列名 |
name | 指定连接表的表名 |
targetEntity | 指定关联实体的类名,默认Hibernate通过反射来判断关联实体的类名 |
joinColumns | 可接受多个 @JoinColumn,用与配置连接表中的外键列信息,这些外键参照当前实体对应表的主键列 |
inverseJoinColumns | 可接受多个 @JoinColumn,用与配置连接表中的外键列信息,这些外键参照关联实体对应表的主键列 |
uniqueConstrains | 为链接表增加唯一约束 |
单向 N-1 关联
1)无连接表的单向 N-1关联示例使用数据表,多个person可能拥有同一个address;table | person |
column | person_id (primary key) |
address_id (foreign key) | |
person_name |
table | address |
column | address_id (primary key) |
address_detial |
import javax.persistence.*; @Entity @Table(name="persion") public class Person { @Id @Column(name="person_id") private int id; @Column(name="persion_name") private String name; //定义Persion实体关联的Address实体 @ManyToOne(targetEntity = Address.class,cascade = CascadeType.ALL) //N-1关联,启用所有级联操作 @JoinColumn(name="address_id",referencedColumnName="address_id" ,nullable = false) //映射外键列 private Address address; //省略所有getter,setter方法 }
address.java
import javax.persistence.*; @Entity @Table(name="address") public class Address { @Id @Column(name="address_id") private int id; @Column(name="addrrss_detail") private String detial; //省略所有 getter,setter方法 }2)有关联表的单向 N-1关联
示例数据表如下:
table | person |
column | person_id (primary key) |
person_name |
table | address |
column | address_id (primary key) |
address_detial |
table | person_address |
column | person_id (foreign key) |
address_id (foreign key) | |
id (primary key) |
import javax.persistence.*; @Entity @Table(name="person") public class Persion { @Id @Column(name="person_id") private int id; @Column(name="person_name") private String name; //定义Persion实体关联的Address实体 @ManyToOne(targetEntity = Address.class,cascade = CascadeType.ALL) //N-1关联,启用所有级联操作 //映射连接表 @JoinTable(name="person_address", //指定连接表名称 joinColumns = @JoinColumn(name="person_id",referencedColumnName = "person_id",unique=true), //连接表外键对当前实体主键的参照 inverseJoinColumns = @JoinColumn(name="address_id",referencedColumnName = "address_id")) //连接表外键对关联实体主键的参照 private Address address; //省略所有getter,setter方法 }
address.java 同上
单向 1-N 关联
对于 1-N 关联,Hibernate 推荐使用双向关联,同时不让1的一端控制关联关系,而使用N的一端控制关联关系,当程序不得不使用使用单向的 1-N,优先采用连接表的 1-N 关联;单向 1-1 关联
单向 1-1 关联一般使用的是无连接表的映射方式;Person.javaimport javax.persistence.*; @Entity @Table(name="person") public class Persion { @Id @Column(name="person_id") private int id; @Column(name="person_name") private String name; //定义Persion实体关联的Address实体 @OneToOne(targetEntity = Address.class,cascade = CascadeType.ALL) //1-1关联,启用所有级联操作 @JoinColumn(name="address_id",referencedColumnName="address_id" ,nullable = false, unique = true) //映射外键列 private Address address; //省略所有getter,setter方法 }
单向 N-N 关联
单向 N-N 关联的代码和 单向 1-N 的代码几乎完全相同,控制关系的一端只需要增加一个Set类型的属性即可;一般 N-N 关联使用连接表的形式进行关联;Person.java@Entity @Table(name="person") public class Persion { @Id @Column(name="person_id") private int id; @Column(name="person_name") private String name; //定义Persion实体关联的Address实体 @ManyToMany(targetEntity = Address.class,cascade = CascadeType.ALL) //N-N关联,启用所有级联操作 //映射连接表 @JoinTable(name="person_address", //指定连接表名称 joinColumns = @JoinColumn(name="person_id",referencedColumnName = "person_id"), //连接表外键对当前实体主键的参照 inverseJoinColumns = @JoinColumn(name="address_id",referencedColumnName = "address_id")) //连接表外键对关联实体主键的参照 private Set<Address> addresses = new HashSet<>(); //省略所有getter,setter方法 }
双向 1-N 关联
大部分时候,双向 1-N 关联使用无连接表的形式进行映射即可;1)无连接表的双向 1-N 关联table | person |
column | person_id (primary key) |
person_name |
table | address |
column | address_id (primary key) |
person_id (foreign key) | |
address_detial |
@Entity @Table(name="person") public class Person { @Id @Column(name="person_id") private int id; @Column(name="person_name") private String name; @OneToMany(targetEntity = Address.class,cascade = CascadeType.ALL,mappedBy = "person") //1-N关联,取消本实体的关联控制 private Set<Address> addresses = new HashSet<>(); //省略所有getter,setter方法 }Address.java
@Entity @Table(name="address") public class Address { @Id @Column(name="address_id") private int id; @Column(name="addrrss_detail") private String detial; @ManyToOne(targetEntity = Person.class,cascade=CascadeType.ALL) @JoinColumn(name="person_id",referencedColumnName = "person_id",nullable = false) private Person person; //省略所有 getter,setter方法 }
2)有连接表的双向 1-N 关联Persion.java
@Entity @Table(name="person") public class Person { @Id @Column(name="person_id") private int id; @Column(name="person_name") private String name; @OneToMany(targetEntity = Address.class,cascade = CascadeType.ALL,mappedBy = "person") //1-N关联,取消本实体的关联控制 private Set<Address> addresses = new HashSet<>(); //省略所有getter,setter方法 }Address.java
@Entity @Table(name="address") public class Address { @Id @Column(name="address_id") private int id; @Column(name="addrrss_detail") private String detial; @ManyToOne(targetEntity = Person.class,cascade=CascadeType.ALL) @JoinTable(name="person_address", joinColumns = @JoinColumn(name="adddress_id",referencedColumnName = "address_id",unique=true), inverseJoinColumns = @JoinColumn(name="person_id",referencedColumnName = "person_id")) private Person person; //省略所有 getter,setter方法 }
双向 1-1 关联
双向 1-1 关联一般使用无连接表的形式进行映射Person.java
@Entity @Table(name="person") public class Person { @Id @Column(name="person_id") private int id; @Column(name="person_name") private String name; @OneToOne(targetEntity = Address.class,cascade = CascadeType.ALL,mappedBy="person") //1-N关联,取消本实体的关联控制 private Address address; //省略所有getter,setter方法 }address.java
@Entity @Table(name="address") public class Address { @Id @Column(name="address_id") private int id; @Column(name="addrrss_detail") private String detial; @ManyToOne(targetEntity = Person.class,cascade=CascadeType.ALL) @JoinColumn(name="person_id",referencedColumnName = "person_id",unique=true) private Person person; //省略所有 getter,setter方法 }
双向 N-N 关联
一般双向N-N关联,使用连接表的形式映射;Person.java@Entity @Table(name="address") public class Address { @Id @Column(name="address_id") private int id; @Column(name="addrrss_detail") private String detial; @ManyToOne(targetEntity = Person.class,cascade=CascadeType.ALL) @JoinColumn(name="person_id",referencedColumnName = "person_id",unique=true) private Person person; //省略所有 getter,setter方法 }Address.java
@Entity @Table(name="address") public class Address { @Id @Column(name="address_id") private int id; @Column(name="addrrss_detail") private String detial; @ManyToOne(targetEntity = Person.class,cascade=CascadeType.ALL) @JoinTable(name="person_address", joinColumns = @JoinColumn(name="adddress_id",referencedColumnName = "address_id"), inverseJoinColumns = @JoinColumn(name="person_id",referencedColumnName = "person_id")) private Set<Person> persons = new HashSet<>(); //省略所有 getter,setter方法 }
继承映射
hibernate 支持将继承层次结构与数据表进行映射,其定义了3种继承映射的策略:① 每个类层次对应一张表的映射策略;② 每个具体类对应一张表的映射策略;③ 连接子类的映射策略;以下使用图示的继承层次进行示例说明:
每个类层次对应一张表的映射策略
这是Hibernate默认的继承映射策略,在这种策略下,整个继承层次结构都储存在一张表中,如上继承层次中 Employee,Regular_Emplee,Constract_Employee 3个实体都储存在同一张表中;使用这种策略时,Hibernate 会为该表额外创建一列,该列用于区分每行记录为哪一个类的实例,该列为辨别者列(discriminiator),使用@DiscriminatorColumn配置辨别者列,Employee.java
@Entity @Table(name = "employee") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) //标注继承方式为单表方式 @DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING) //指定辨别者列的数据类型 @DiscriminatorValue(value="employee") //指定该实体的辨别者列值 public class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private int id; @Column(name = "name") private String name; // setters and getters }Regular_Employee.java
@Entity @DiscriminatorValue("regularemployee") public class Regular_Employee extends Employee { @Column(name = "salary") private float salary; @Column(name = "bonus") private int bonus; // setters and getters }Contract_Employee.java
@Entity @DiscriminatorValue("contractemployee") public class Contract_Employee extends Employee { @Column(name = "pay_per_hour") private float pay_per_hour; @Column(name = "contract_duration") private String contract_duration; // setters and getters }
每个具体类对应一张表的映射策略
这一种策略为每一个具体类对应一个具体的数据表,一般不会使用这种策略,因为有可能会导致数据过渡冗余;Employee.java@Entity @Table(name = "employee") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private int id; @Column(name = "name") private String name; // setters and getters }
Regular_Employee.java
@Entity @Table(name = "regularemployee") @AttributeOverrides({ @AttributeOverride(name = "id", column = @Column(name = "id")), @AttributeOverride(name = "name", column = @Column(name = "name")) }) public class Regular_Employee extends Employee { @Column(name = "salary") private float salary; @Column(name = "bonus") private int bonus; // setters and getters }Contract_Employee.java
@Entity @Table(name = "contractemployee") @AttributeOverrides({ @AttributeOverride(name = "id", column = @Column(name = "id")), @AttributeOverride(name = "name", column = @Column(name = "name")) }) public class Contract_Employee extends Employee { @Column(name = "pay_per_hour") private float pay_per_hour; @Column(name = "contract_duration") private String contract_duration; // setters and getters }
连接子类的映射策略
采用这种映射策略时,父类的实体保存在父类表里,而子类的实体则由父类表和子类表共同储存,即将子类和父类共同的属性存储在父类表中;Employee.java@Entity @Table(name = "employee") @Inheritance(strategy = InheritanceType.JOINED) public class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private int id; @Column(name = "name") private String name; // setters and getters }Regular_Employee.java
@Entity @Table(name = "regularemployee") @PrimaryKeyJoinColumn(name = "id") public class Regular_Employee extends Employee { @Column(name = "salary") private float salary; @Column(name = "bonus") private int bonus; // setters and getters }Contract_Employee.java
@Entity @Table(name = "contractemployee") @PrimaryKeyJoinColumn(name = "id") public class Contract_Employee extends Employee { @Column(name = "pay_per_hour") private float pay_per_hour; @Column(name = "contract_duration") private String contract_duration; // setters and getters }
相关文章推荐
- hibernate一对一唯一外键关联映射(单向关联Person----->IdCard)
- Hibernate从入门到精通(九)一对多双向关联映射
- Hibernate入门08 - 继承映射1
- Hibernate从入门到精通(八)一对多单向关联映射
- Hibernate从入门到精通(九)一对多双向关联映射
- Hibernate 、继承关联映射
- Hibernate入门09 - 继承映射2
- 闲来无事,复习复习以前的东西---hibernate中的关联映射图解 ---- 继承映射
- Hibernate从入门到精通(八)一对多单向关联映射
- Hibernate从入门到精通(九)一对多双向关联映射
- Hibernate笔记=>继承关系的映射
- hibernate中的关联映射图解 ---- 继承映射
- hibernate注解版关联映射Many-to-One/Many-to-Many等&异常处理
- Hibernate入门07_继承映射03_union方式
- hibernate学习笔记-2入门初体验关联映射
- Hibernate入门08 - 继承映射1
- hibernate学习笔记-2入门初体验关联映射
- Hibernate4自学入门(九)——映射继承
- Hibernate学习17 -- 关联映射7 -- 继承映射1 -- 一张表存储
- Hibernate入门09 - 继承映射2