JPA的关联查询,@JoinColumn,@JoinTable的使用

前提:A 表和 B 表为oneToMany的关系,B中属性a_id为外键。

单向关系和双向关系:双向为A、B entity类中都依赖对方,循环依赖,双向才需要指定mappedBy。

在@oneToMany、@ManyToMany、@OneToOne能定义mappedBy,@ManyToOne不能。定义了mappedBy的属性,或者说A的entity中不能再使用@JoinColumn,@JoinTable。

双向:

A中注解 
@OneToMany(mappedBy = "a") 
private List blist;
B中注解
@ManyToOne(targetEntity = A.class) 
@JoinColumn(name="a_id", referencedColumnName = "id")
private A a;

单向,@JoinColumn方式:

A或B中注解
@OneToMany
@JoinColumn(name = "a_id", referencedColumnName = "id")
private List blist;
//@ManyToOne
//@JoinColumn(name = "a_id", referencedColumnName = "id")
//private A a;

单向,@JoinTable方式:

A或B中注解
@OneToMany
@JoinTable(name = "A_B", 
joinColumns = @JoinColumn(name = "a_id", referencedColumnName ="id"),
inverseJoinColumns = @JoinColumn(name="b_id", referencedColumnName ="id"))
private List blist;

//@ManyToOne
//@JoinTable(name = "A_B", 
//joinColumns = @JoinColumn(name = "b_id", referencedColumnName ="id"),
//inverseJoinColumns = @JoinColumn(name="a_id", referencedColumnName ="id"))
//private A a;

N+1 问题: 当A表中有n条数据, 需要查询1次A表,再查询B表N次。 反过来ManyToOne, N也是对于A表的n条数据。

双向:以ARepository查询为例
情况一:A饿加载,无视B的FetchType。
N 对应的查询sql语句是只查B表。
B中声明的A属性指向与自身关联的A对象。 a.equals(a.getBlist().get(0).getA()) == true
情况二:A懒加载,B饿加载。 
N 对应的查询sql语句是分开先后查B,A表。B中声明的A属性是一个新对象。 懒加载get不会执行sql,sysout才会。
情况三:A懒加载,B懒加载。
N 对应的查询sql语句是只查B表。 a.getBlist().get(0).getA()获取A时才会查A表,B中声明的A属性是一个新对象。

单向@JoinColumn方式:

懒饿加载一样,N 对应的查询sql语句是只查B表或只查A表。

单向@JoinTable方式:

a_id和b_id属于A_B中间表的字段。 joinColumns是中间表和本entity的mapping,inverseJoinColumns是中间表和另一个entity的mapping。

referencedColumnName 必须是A,B主键。基于此,B中的外键就无用了,B->A_B为一对一,A->A_B为一对多。

@OneToMany,懒饿加载一样,N 对应的查询sql语句是join。

@ManyToOne,懒饿加载一样,1对应的sql语句是join。 N 对应的查询sql语句是A表。 

你可能感兴趣的:(JPA,sql,java,hibernate)