hibernate之数据库注解关联关系

一、           单项N-1关联

在单项关联和双向关联,都需要在N的一段使用@ManyToOne修饰关联实体的属性。

@ManyToOne支持的属性

属性

是否必须

说明

cascade

指定Hibernate对关联实体采样怎样的级联策略

CascadeType.ALL:Hibernate将所有的持久化操作都级联到关联实体

CascadeType.MERGE:Hibernate将merge操作级联到关联实体

CascadeType.PERSIST: Hibernate将persist操作级联到关联实体

CascadeType.REFRESH: Hibernate将refresh操作级联到关联实体

CascadeType.REMOVE: Hibernate将remove操作级联到关联实体

fetch

指定抓取关联实体时的抓取策略,

FetchType.EAGER:立即抓取关联实体,默认

FetchType.LAZY: 延迟抓取关联实体。真正用到关联实体才抓取

optional

关联关系是否可选

targetEntity

指定关联实体的类名。默认情况下将通过反射来判断关联实体的类名

使用注意:在@OneToMany、@ManyToMany修饰的1-N、N-N关联中,关联实体的Set集合不带泛型信息,必须指定此属性

1.    无连接表的N-1关联

@Entity

@Table(name="address_inf")

public class Address {

   @Id @Column(name="address_inf")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private int addressId;

}

public class Person {

 

  

   //标识属性

   @Id @Column(name="person_id")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private Integer id;

   //定义该Person实体关联的Address实体

   @ManyToOne(targetEntity=Address.class)

   //映射外键列,指定外键列的列名为address_id,不允许为空

   @JoinColumn(name="address_id",nullable=false)

   @Cascade(CascadeType.ALL)

   private Address address;

   }

2.    有连接表的N-1关联

使用连接表来映射单项N-1关联,程序需要显式使用@JoinTable注解来映射连接属性

@JoinTable支持的属性

属性

是否必须

说明

name

指定链接表表明

catalog

将连接表放入指定catalog中。没有指定该属性则放入默认catalog中

schema

将连接表放入指定schema中。没有指定该属性则放入默认schema中

targetEntity

指定关联实体类名,默认情况下通过反射来判断关联实体类名

indexes

@Index注解数组,为连接表定义多个索引

joinColumns

可接受多个@JoinColumn,用于配置连接表中外键列的列信息,这些外键列参照当前实体对应表的主键列

inverseJoinColumns

接受多个@JoinColumn,用于配置链接表中外键列信息,这些外键列参照当前实体的关联实体对应的主键列

uniqueConstrains

为链接表增加唯一约束

Class Person{

       //标识属性

     @Id @Column(name="person_id")

     @GeneratedValue(strategy=GenerationType.IDENTITY)

     private Integer id;

     //定义该Person实体关联的Address实体

     @ManyToOne(targetEntity=Address.class)

     //显式使用@JoinTable映射连接表

     @JoinTable(name="person_address",//指定链接表的表名为person_address

     //指定链接表中person_id外键列,参照当前实体对应表的主键列

     joinColumns=@JoinColumn(name="person_id", referencedColumnName="person_id",unique=true),

     //指定链接表中address_id外键列,参照到当前实体关联实体对应表的主键列

     inverseJoinColumns=@JoinColumn(name="address_id", referencedColumnName="address_id")

     )

 

     private Address address;

}

二、           单向1-1关联

对于1-1关联 单/双项关联需要使用@OneToOne修饰代表关联实体的属性

@OneToOne支持的属性

属性

是否必须

说明

cascade

指定Hibernate对关联实体采样怎样的级联策略

CascadeType.ALL:Hibernate将所有的持久化操作都级联到关联实体

CascadeType.MERGE:Hibernate将merge操作级联到关联实体

CascadeType.PERSIST: Hibernate将persist操作级联到关联实体

CascadeType.REFRESH: Hibernate将refresh操作级联到关联实体

CascadeType.REMOVE: Hibernate将remove操作级联到关联实体

tetch

指定抓取关联实体时的抓取策略,

FetchType.EAGER:立即抓取关联实体,默认

FetchType.LAZY: 延迟抓取关联实体。真正用到关联实体才抓取

MappedBy

该属性合法的属性值为关联实体的属性名,该属性指定关联实体中哪个属性可引用到当前实体

orphanRemoval

该属性设置是否删除孤儿实体。如果某个实体所关联的父实体不存在(既实体对应记录的外键为null),该实体就是所谓的孤儿实体

optional

关联关系是否可选

targetEntity

指定关联实体的类名。默认通过反射来判断关联实体名

1)    基于外键的单项1-1关联

Person class{}

//标识属性

     @Id @Column(name="person_id")

     @GeneratedValue(strategy=GenerationType.IDENTITY)

     private Integer id;

     //定义该Person实体关联的Address实体

     @OneToOne(targetEntity=Address.class)

     //显式使用@JoinTable映射连接表

     @JoinTable(name="person_address",//指定链接表的表名为person_address

     //指定链接表中person_id外键列,参照当前实体对应表的主键列

     joinColumns=@JoinColumn(name="person_id", referencedColumnName="person_id",unique=true),

     //指定链接表中address_id外键列,参照到当前实体关联实体对应表的主键列

     inverseJoinColumns=@JoinColumn(name="address_id", referencedColumnName="address_id")

     )

 

     private Address address;

2)    有连接表的单项1-1关联

Person class{}

//标识属性

     @Id @Column(name="person_id")

     @GeneratedValue(strategy=GenerationType.IDENTITY)

     private Integer id;

     //定义该Person实体关联的Address实体

     @OneToOne(targetEntity=Address.class)

     //显式使用@JoinTable映射连接表

     @JoinTable(name="person_address",//指定链接表的表名为person_address

     //指定链接表中person_id外键列,参照当前实体对应表的主键列

     joinColumns=@JoinColumn(name="person_id", referencedColumnName="person_id",unique=true),

     //指定链接表中address_id外键列,参照到当前实体关联实体对应表的主键列

     inverseJoinColumns=@JoinColumn(name="address_id", referencedColumnName="address_id")

     )

 

     private Address address;

三、 单项1-N关联

a)    无连接表的单项1-N关联

需要在N的一端增加外键列来维护关联关系,可在1的一端使用@JoinColumn修饰Set集合属性、映射外键列即可

Class person{

//标识属性

   @Id @Column(name="person_id")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private Integer id;

   //定义该Person实体关联的Address实体,没有指定cascade属性

   @OneToMany(targetEntity=Address.class)

   //映射外键列,此处映射的外键列将会添加到关联实体对应的数据表中

   @JoinColumn(name="address_id", refrencedColumnName="address_id",unique=true)

 

   private Set<<Address> address = new HashSet<>();

}

b)   有连接表的单项1-N关联

Class Person{

//标识属性

   @Id @Column(name="person_id")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private Integer id;

   //定义该Person实体关联的Address实体

   @OneToMany(targetEntity=Address.class)

   //显式使用@JoinTable映射连接表

   @JoinTable(name="person_address",//指定链接表的表名为person_address

   //指定链接表中person_id外键列,参照当前实体对应表的主键列

   joinColumns=@JoinColumn(name="person_id", referencedColumnName="person_id",unique=true),

   //指定链接表中address_id外键列,参照到当前实体关联实体对应表的主键列

   inverseJoinColumns=@JoinColumn(name="address_id", referencedColumnName="address_id",unique=true)

   )

 

   private Address address;

}

四、单向N-N关联

单向N-N关联和1—N关联的持久化代码完全相同,控制关系的一端需要增加一个Set类型的属性,被关联的持久化实例以集合形式存在。

       N-N关联需要使用@ManayToMany注解来修饰代表关联实体的集合属性,其属性如下

属性

是否必须

说明

cascade

指定Hibernate对关联实体采样怎样的级联策略

CascadeType.ALL:Hibernate将所有的持久化操作都级联到关联实体

CascadeType.MERGE:Hibernate将merge操作级联到关联实体

CascadeType.PERSIST: Hibernate将persist操作级联到关联实体

CascadeType.REFRESH: Hibernate将refresh操作级联到关联实体

CascadeType.REMOVE: Hibernate将remove操作级联到关联实体

fetch

指定抓取关联实体时的抓取策略,

FetchType.EAGER:立即抓取关联实体,默认

FetchType.LAZY: 延迟抓取关联实体。真正用到关联实体才抓取

mappedBy

该属性合法的属性值为关联实体的属性名,该属性指定关联实体中哪个属性可引用到当前实体

targetEntithy

指定关联实体的类名。默认通过反射来判断关联实体名

、N-N关联必须使用连接表,与1-N关联相似,都要使用@JoinTable映射,区别是:N-N关联需要去掉@JoinTable中inverseJoinColumns中@JoinColumn的unique=true

@Entity

 

@Table(name="person_inf")

public class Person {

 

   //标识属性

     @Id @Column(name="person_id")

     @GeneratedValue(strategy=GenerationType.IDENTITY)

     private Integer id;

     //定义该Person实体关联的Address实体

     @ManyToMany(targetEntity=Address.class)

     //映射连接表为person_address

     @JoinTable(name="person_address",//指定链接表的表名为person_address

     //定义链接表中名为person_id外键列,参照当前实体对应表的主键列

     joinColumns=@JoinColumn(name="person_id", referencedColumnName="person_id",unique=true),

     //指定链接表中address_id外键列,参照到当前实体关联实体对应表的主键列 没有指定unique=true

     inverseJoinColumns=@JoinColumn(name="address_id", referencedColumnName="address_id",unique=true)

     )

 

     private Set<Address> address = new HashSet<>();

}

五、双向N-N关联

       双向N-N关联需要两端都是用Set集合属性,两端都增加对集合属性的访问。只能使用链接表建立关联

       双向N-N关联需要在两端分别使用@ManyToMany修饰Set集合属性,并在两端都使用@JoinTable显式映射链接表。在两端映射连接表时,两端指定的连接表的表明应该相同,而且两端都使用@JoinTable时指定的外键列的列名也是相互对应的。

       如果希望某一段放弃控制关联关系,则可在这一端的@ManyToMany注解中指定mappedBy属性,这一端就无需、也不能使用@JoinTable映射连接表

       例如:Person和Address都保持双向N-N关联关系

@Entity

@Table(name="person_inf")

public class Person {

 

   //标识属性

     @Id @Column(name="person_id")

     @GeneratedValue(strategy=GenerationType.IDENTITY)

     private Integer id;

     //定义该Person实体关联的Address实体

     @ManyToMany(targetEntity=Address.class)

     //映射连接表为person_address

     @JoinTable(name="person_address",//指定链接表的表名为person_address

     //定义链接表中名为person_id外键列,参照当前实体对应表的主键列

     joinColumns=@JoinColumn(name="person_id", referencedColumnName="person_id"),

     //指定链接表中address_id外键列,参照到当前实体关联实体对应表的主键列 没有指定unique=true

     inverseJoinColumns=@JoinColumn(name="address_id", referencedColumnName="address_id",unique=true)

     )

 

     private Set<EAddress> address = new HashSet<>();

}

Address实体

@Entity

@Table(name="address_inf")

public class Address {

   @Id @Column(name="address_inf")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private int addressId;

   //定义地址详细信息的成员变量

   private String addressDetail;

   //定义该Address实体所有关联的Person实体

   @ManyToMany(targetEntity=person.class)

   //映射连接表、指定链接表的表名为person_address

   @JoinTable(name="person_address",

   //映射连接表中名为address_id的外键列

   //该列参照当前实体对应表address_id主键列

joinColumns=@JoinColumn(name="address_id",referencedColumnName="address_id"),

   //映射链接表中名为person_id的外键列

   //该列参照当前实体对应表的person_id主键列

inverseJoinColumns=@JoinColumn(name="person_id",referencedColumnName="person_id"))

   private Set<Person> persons = new HashSet<>()

}

六、双向1-1关联

       双向1-1关联需要修改两端的持久化类代码,让两个持久化类都增加引用关联实体的属性,并为属性提供setter和getter方法

1.基于外键的双向1-1关联

       对于双向1-1关联,两端都需要使用@OneToOne注解进行映射

       对于基于外键的双向1-1关联,外键可以存放在任意一端。存放外键的一端,需要增加@JoinColumn注解来映射外键列,还应该增加@JoinColumn注解增加unique=true属性来表示该实体实际上是1的一端。

       对于1-1的关联关系,两个实体原本处于平等状态;但选择任意一端增加外键(增加@JoinColumn注解的实体端),该表既变成从表,而另一个表则成为主表。

       对于双向1-1的关联的主表对应的实体,不用于控制关联关系,主表对应的实体中使用@OneToOne注解时,应增加mappedBy属性------该属性表明该实体不管理关联关系,且不能使用@JoinColumn映射外键列

@Entity

 

@Table(name="person_inf")

public class Person {

 

   //标识属性

   @Id @Column(name="person_id")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private Integer id;

   //定义该Person实体关联的Address实体

@OneToOne(targetEntity=Address.class,mappedBy="person")

   private Address address2;

}

@Entity

@Table(name="address_inf")

public class Address {

  

   @Id @Column(name="address_inf")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private int addressId;

   //定义地址详细信息的成员变量

   private String addressDetail;

   //定义该Address实体所有关联的Person实体

   @OneToOne(targetEntity=Person.class)

   //用于映射person_id外键列,参照person_if表的person_id列

   //指定了unique=true表明是1-1关联

@JoinColumn(name="person_id",referencedColumnName="person_id",unique=true)

   private Person person;

}

2.有连接表的双向1-1关联

有连接表的双向1-1关联需要在两端分别使用@ OneToOne修饰代表关联实体的属性,并在两端都使用@JointTable显式映射连接表。在映射连接表时,两端指定的连接表的表名应该相同,而且两端使用@JoinTable时指定的外键列的列名也是相互对应的。

需要说明的是,如果程序希望某一端放弃控制关联关系,则可在这一端的@ OneToOne注解中指定mappedBy属性,这一端就无须、也不能使用@JoinColumn映射连接表了。由于此时是1-1关联,因此使用@ JoinTable注解时指定的@ JoinColum都需要增加 unique=true.

@Entity

 

@Table(name="person_inf")

public class Person {

  

// 标识属性

   @Id @Column(name="person_id")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private Integer id;

   //定义该Person实体关联的Address实体

   @OneToOne(targetEntity=Address.class)

   //映射底层连接表,表名为person_address

   @JoinTable(name="person_address",//

   //映射链接表的外键列,增加unique=true表明是1-1关联

   joinColumns=@JoinColumn(name="person_id", referencedColumnName="person_id",unique=true),

   //映射链接表的外键列,增加unique=true表明是1-1关联

   inverseJoinColumns=@JoinColumn(name="address_id", referencedColumnName="address_id",unique=true)

   )

   private Address address2;

}

@Entity

@Table(name="address_inf")

public class Address {

  

  

   @Id @Column(name="address_inf")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private int addressId;

   //定义地址详细信息的成员变量

   private String addressDetail;

   //定义该Address实体所有关联的Person实体

   @OneToOne(targetEntity=Person.class)

   //映射底层连接表,表名为person_address 指定了unique=true表明是1-1关联

   @JoinTable(name="person_address",//

   //映射链接表的外键列,增加unique=true表明是1-1关联

   joinColumns=@JoinColumn(name="address_id", referencedColumnName="address_id",unique=true),

   //映射链接表的外键列,增加unique=true表明是1-1关联

   inverseJoinColumns=@JoinColumn(name="person_id", referencedColumnName="person_id",unique=true))

   private Person person;

}

七、双向1-N关联

对于1-N关联, Hibernate推荐使用双向关联,而且不要让1的一端控制关联关系,而使用N的

控制关联关系。双向的1-N关联与N-1关联是完全相同的两种情形,两端都需要地加对关联属性的访间,N的一端增加引用到关联实体的属性,1的一端增加集合属性,集合元素为关联实体

Hibernate同样对这种双向关联映射提供了两种支持:有连接表的和无连接表的,

1.无连接表的双向1-N关联

       无连接表的双向1-N关联,N的一端需要增加 @Many ToOne注解来修饰代表关联实体的属性,而1的一端则需要使用@ OneToMany注解来修饰代表关联实体的属性关系,实际上只需要在N的底层数据库为了记录这种1-N关联既可,因此应该在使用@ ManyToOne注解的同时,使用@JoinColumn来映射外键。

       前面己经提到,对于双向的1-N关联映射,通常不应该允许1的一端控制关联关系,而应该由N的一端来控制关联关系,因此应该在使用@OneToMany注解时指定 mappedBy属性-------一旦为@OneToMany, @ManyToMany指定了该属性,则表明当前实体不能控制关联关系,当@OneToMany@ManyToMany、@OneToOne所在的当前实体放弃控制关联关系之后, Hibernate就不允许使用@JoinColumn或@ JoinTable修饰代表关联实体的属性了。

       对于指定了 mappedBy属性的@ OneToMany.@ ManyToMamy、@OneToOne注解不能与@ JoinColum或@ JoinTable同时修饰代表关联实体的属性

@Entity

 

@Table(name="person_inf")

public class Person {

  

   标识属性

   @Id @Column(name="person_id")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private Integer id;

   //定义该Person实体关联的Address实体

   //指定mappedBy属性表明该Person实体不控制关联关系

@OneToMany(targetEntity=Address.class,mappedBy="person")

   private Set<Address> address = new HashSet<>();

}

@Entity

@Table(name="address_inf")

public class Address {

   @Id @Column(name="address_inf")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private int addressId;

   //定义地址详细信息的成员变量

   private String addressDetail;

   //定义该Address实体所有关联的Person实体

   @ManyToOne(targetEntity=Person.class)

   //定义名为person_id外键列,参照person_inf表的person_id列

   //指定了unique=true表明是1-1关联

@JoinColumn(name="person_id",referencedColumnName="person_id",nullable=false)

   private Person person;

}

2.有连接的双向1-N关联

有连接的双向1-N关联,1的一端无需任何改变;只要在N的一端使用@JoinTable显式指定连接表即可。

@Entity

@Table(name="address_inf")

public class Address {

   @Id @Column(name="address_inf")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private int addressId;

   //定义地址详细信息的成员变量

   private String addressDetail;

   //定义该Address实体所有关联的Person实体

   @ManyToOne(targetEntity=Person.class)

   //映射连接表,指定连接表为person_address

// @JoinTable(name="person_address",//

// //指定连接表中address_id列参照当前实体对应数据表的address_id主键列

// joinColumns=@JoinColumn(name="address_id", referencedColumnName="address_id",unique=true),

// //指定连接表中person_id列参照当前实体关联实体的对应数据表的person_id主键列

// inverseJoinColumns=@JoinColumn(name="person_id", referencedColumnName="person_id"))

   private Person person;

}

@Entity

@Table(name="person_inf")

public class Person {

//标识属性

   @Id @Column(name="person_id")

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private Integer id;

   //定义该Person实体关联的Address实体

   @OneToMany(targetEntity=Address.class)

   //映射底层连接表,表名为person_address

   @JoinTable(name="person_address",//

   //指定连接表中address_id列参照当前实体对应数据表的person_id主键列

   joinColumns=@JoinColumn(name="person_id", referencedColumnName="person_id"),

   //指定连接表中address_id列参照当前实体关联实体的对应数据表的address_id主键列

   inverseJoinColumns=@JoinColumn(name="address_id", referencedColumnName="address_id",unique=true)

        )

 

   private Set<Address> address = new HashSet<>();

}

对于所有的依赖关系期望先持久化一的一端,再持久化N的一端,或者先持久化被依赖的一端

原文地址:https://www.cnblogs.com/sundaysjava/p/10332387.html