【JavaEE】经典JAVA EE企业应用实战-读书笔记16

从关联关系的数量上来看,单向关联可分为

1)单向1-1

2)单向1-N

3)单向N-1

4)单向N-N

从关联关系的数量上来看,双向关联可分为

1)双向1-1

2)双向1-N

3)双向N-N

 

单向N-1

public class Address{
  @ManyToOne(opentional=false,cascade=CascadeType.ALL,fetch=FetchType.LAZY,targetEntity=Person.class)
  //下面的注解用于映射外键列
  @JoinColumn(name=”person_id”,nullable=false,updatable=false)
  private Person person;
}

对于1-N关联关系,不管是单向还是双向,都需要在N的一端使用@ManyToOne

cascade:非必须,指定JPA采用怎样的级联策略

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

2)CascadeType.MERGE:将merge操作都级联到关联实体

3)CascadeType.PERSISI:将persist操作都级联到关联实体

4)CascadeType.REFRESH:将refresh操作都级联到关联实体

5)CascadeType.REMOVE:将remove操作都级联到关联实体

fetch:非必须,指定抓取关联实体时的抓取策略,支持

1)FetchType.EAGER:立即抓取关联实体。默认值

2)FetchType.LAZY:延迟抓取关联实体。

optional:非必须,指定关联关系是否可选

targetEntity:非必须,指定关联实体的类名。默认情况下JPA将通过反射来判断关联实体的类名

 

@JoinColumn属性说明

1)columnDefinition,非必须,指定JPA使用该属性值指定SQL片段来创建外键列

2)name:非必须,指定外键列的列名

3)insertable:非必须,指定该列是否包含在JPA生成的insert语句中,默认为true

4)updatable:非必须,指定该列是否包含在JPA生成的update语句中,默认为true

5)nullable:非必须,指定该列是否允许null,默认为true

6)table:非必须,指定该列所在数据表的表名

7)unique:非必须,指定是否为该列增加唯一约束

8)referencedColumnName:非必须,指定该列所参照的主键列的列名

可以使用@JoinColumns来组合@JoinColumn

 

单向1-1

使用@OneToOne来修饰,属性说明

cascade:非必须,取值同上

fetch:非必须,取值同上

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

optional:非必须,同上

targetEntity:非必须,同上

对于mappedBy属性,可在@OneToOne@OneToMany@ManyToMany中使用,不能在@ManyToOne中使用,除了上述的作用外,还用于指定该属性出现的当前实体不再控制关联关系——类似于Hibernate中设置了inver=”true”。一旦为@OneToMany@ManyToMany指定了mappedBy属性,这两个Annotation将不能和@JoinColumn@JoinTable一起使用。

外键列会被添加唯一约束

 

单向1-N

实体类需要使用集合属性,以set形式出现。这样,1-N(还包括N-N)都需要增加一个set类型的属性

推荐在@OneToOne@OneToMany@ManyToOne@ManyToMany这四个注解中指定targetEn。指定该属性可以避免JPA通过反射去获取关联实体的类型,从而提高性能。

1-N关联需要使用@OneToMany来修饰Set属性,属性说明

cascade:非必须,取值同上

fetch:非必须,取值同上

mappedBy:非必须,取值同上

targetEntity:非必须,取值同上

public class Person{
  @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,targetEntity=Address.class)
  @JoinColumn(name=”person_id”,nullable=false)
  private Set<Address>=new HashSet<Address>();
}
单向N-N

N-N的关联必须使用中间表。除了使用@ManyToMany来修饰Set外,还需要使用@JoinTable来修饰Set

@ManyToMany属性如下

cascade:非必须,取值同上

fetch:非必须,取值同上

mappedBy:非必须,取值同上

targetEntity:非必须,取值同上

@JoinTable专门用于N-N关系,属性如下

name:非必须,指定该连接表的表名

catalog:非必须,设置实体所映射的表放入指定的catalog内,如果没有则放入默认的catalog

schema:非必须,设置实体锁映射的表放入指定的schema内,如果没有则放入默认的schema

targetEntity:非必须,取值同上

joinColumns:非必须,接受多个@JoinColumn,用于配置外键列信息,参照当前实体的主键列

inverseJoinColumns:非必须,接受多个@JoinColumn,用于配置外键列信息,参照当前实体的关联实体的主键列

uniqueConstraints:非必须,用于为中间表增加唯一约束

public class Peson{
  @ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,targetEntity=Address.class)
  @JoinTable(name=”person_address”,joinColumns=@JoinColumn(name=”person_id”)inverseJoinColumns=@JoinColumn(name=”address_id”))
  private Set<Address> address=new HashSet<Address>();
}

双向1-1

需要在两边的实体类增加@OneToOne修饰属性,可以在关联实体一边的@OneToOne中增加mappedBy属性,增加改属性的实体不再控制关联关系

public class Person{
  @OneToOne(mappedBy=”person”,cascade=CascadeType.ALL,fetch=FetchType.LAZY,targetEntity=Address.class)
  private Address address;
}

上例中Person不再控制关联关系,所以Person的关联实体Address就需要控制关联关系,由于JPA会采用基于外键的方式来建立底层数据库中1-1关联关系,因此在Address中还需要使用@JoinColumn

public class Address{
  @OneToOne(optional=false,cascade=CascadeType.ALL,fetch-FetchType.LAZY,targetEntity=Person.class)
  @JoinColumn(name=”person_id”,nullable=false,updatable=false)
  private Person person;
}

需要指出的是,由于1-1关联的双方本质上是平等的,一次底层数据库可以在1-1关联的两个数据表的任意一边增加外键列,并通过外键列来维护实体之间的参照关系。但对于JPA而言,需要一个具体的规则:如果双向1-1关联的某个实体类中的@OneToOne没有指定mappedBy属性,并使用了@JoinColumn,那么JPA将会在该实体对应的数据表中增加外键列。因此对于上面的程序,JPA会在Address实体对应的数据表中增加外键列。

 

双向1-N关联

对于1-N关联,在JPA中应该尽量映射成双向关联,而且尽量不要让1的一端来控制关联关系,而应该在N的一端来控制关联关系

双向的1-NN-1是完全相同的两种情形。

1的一端应该使用@OneToMany修饰记录关联实体的Set属性,由于程序通常不会让1的一端来控制关联关系,因此使用@OneToMany时应增加mappedBy属性,N的一端则应该使用@ManyToOne修饰记录关联实体的属性。除此之外,还应该在N的一端的实体上使用@JoinColumn来配置外键列信息。

public class Peson{
  // 1端的代码
  @OneToMany(cascade=CascadeType.ALL,mappedBy=”person”,targetEntity=Address.class)
  private Set<Address> addresses;
}
public class Address{
  // N端的代码
  @ManyToOne(fetch=FetchType.EAGER,targetEntity=Person.class,cascade=CascadeType.ALL)
  @JoinColum(name=”person_id”,nullable=true)
  private Person person;
}
双向N-N 关联

关联实体的两边都应该增加set属性,两边都使用@ManyToMany来修饰,需要在一端的关联实体中增加@JoinTable来管理连接表信息。可通过在一端的@ManyToMany中增加mappedBy属性,增加该属性的实体将不再控制关联关系,因此该实体的set属性不应该使用#JoinTable修饰

public class Address{
  @ManyToMany(cascade=CascadeType.ALL,mappedBy=”addresses”,fetch=FecthType.LAZY,targetEntity=Person.class)
  private Set<Person> persons=new HashSet<Person>();
}
public class Person{
  @ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,targetEntity=Address.class)
  @JoinTable(
    name=”person_address”,
    joinColumns=@JoinColumn(name=”person_id”),
    inverseJoinColumn=@JoinColumn(name=”address_id”)
  )
  private Set<Address> addresses=new HashSet<Address>();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值