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

本文详细解析了Java中A表和B表的oneToMany关系,区别了双向与单向映射,以及如何避免N+1问题。涵盖了双向关系的 mappedBy、@JoinColumn与@JoinTable的使用,以及不同加载策略对查询的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前提: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<B> 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<B> 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<B> 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表。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值