Spring JPA聯(lián)表查詢之OneToMany源碼解析
前言
我們?cè)趯?shí)際項(xiàng)目中,除了會(huì)碰到一對(duì)一的情況,還有一對(duì)多的情況,比如一個(gè)用戶可以有多輛車,而一輛車只能有一個(gè)用戶等等,今天我們就來(lái)一起學(xué)習(xí)下 OneToMany(一對(duì)多)。
源碼
@OneToMany 注解實(shí)現(xiàn)一對(duì)多關(guān)系映射。比如用戶跟房子的關(guān)系, 一個(gè)用戶可以有好多房子,而一個(gè)房子只能一個(gè)用戶。
老規(guī)矩,實(shí)例之前先看看源碼:
public @interface OneToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default LAZY;
String mappedBy() default "";
boolean orphanRemoval() default false;
}
注解屬性詳情請(qǐng)見(jiàn) 注解屬性詳解,其中需要注意的是 @OneToMany 的 fetch 的默認(rèn)值是 LAZY。
單向聯(lián)表
我這里所說(shuō)的單向聯(lián)表就是只有一方添加注解;通俗講就是我可以通過(guò) user 獲取到其 house 的信息,而不同通過(guò) house 獲取到其 user 的信息。
user 實(shí)體類
因?yàn)閷?duì)方是 many 多端,所以這邊需要用 List 集合
@Entity
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private int age;
@OneToMany
@JoinColumn(name = "user_id")
private List<House> house;
}
house 實(shí)體類
@Entity
@Data
public class House {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String addr;
}
小貼士
實(shí)例運(yùn)行之后,大家肯定會(huì)發(fā)現(xiàn)一個(gè)奇怪的問(wèn)題:user_id 字段明明寫在了 user 實(shí)體類中,但是實(shí)際卻添加在 house 表中,這是為啥呢?
因?yàn)樵?JPA 規(guī)范中,一對(duì)多的雙向關(guān)系是由 多端(many) 來(lái)維護(hù)。就是說(shuō) 多端(many) 為關(guān)系維護(hù)端,負(fù)責(zé)關(guān)系的增刪改查;一端(one) 則為關(guān)系被維護(hù)端。
執(zhí)行請(qǐng)求/user/findById?id=1,控制臺(tái)打印如下:
Hibernate:
select
user0_.id as id1_2_0_,
user0_.age as age2_2_0_,
user0_.name as name3_2_0_
from
user user0_
where
user0_.id=?
Hibernate:
select
house0_.user_id as user_id3_1_0_,
house0_.id as id1_1_0_,
house0_.id as id1_1_1_,
house0_.addr as addr2_1_1_
from
house house0_
where
house0_.user_id=?
查詢結(jié)果
User(id=1, name=lili, age=11, house=[House(id=1, addr=江蘇南京), House(id=2, addr=江蘇無(wú)錫), House(id=3, addr=江蘇蘇州)])
雙向聯(lián)表
我們除了需要通過(guò) user 信息來(lái)獲取其 house 信息外,有時(shí)還需要通過(guò) house 信息來(lái)獲取其 user 信息。但是需要注意的是 user 對(duì)于 house 來(lái)說(shuō),是一對(duì)多;而 house 對(duì)于 user 來(lái)說(shuō),是多對(duì)一。這時(shí)我們就需要引入另一個(gè)聯(lián)表注解 @ManyToOne,在 house 的實(shí)體中添加 user 字段,并添加 @ManyToOne 注解。(這里有一個(gè)堆棧溢出的問(wèn)題需要注意一下,詳情請(qǐng)見(jiàn) JPA 錯(cuò)題集 第二個(gè)報(bào)錯(cuò)信息)
user 實(shí)體類
user 實(shí)體中 house 字段
@OneToMany @JoinColumn(name = "user_id") @JsonIgnore public List<House> house;
house 實(shí)體類
@ManyToOne @JsonIgnore private User user;
執(zhí)行請(qǐng)求 /house/findById?id=1,控制臺(tái)打印如下:
Hibernate:
select
house0_.id as id1_1_0_,
house0_.addr as addr2_1_0_,
house0_.user_id as user_id3_1_0_,
user1_.id as id1_2_1_,
user1_.age as age2_2_1_,
user1_.name as name3_2_1_
from
house house0_
left outer join
user user1_
on house0_.user_id=user1_.id
where
house0_.id=?
2023-04-27 20:35:29.940 TRACE 24272 --- [nio-7777-exec-6] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [INTEGER] - [1]
對(duì)象獲取
有同學(xué)可能已經(jīng)發(fā)現(xiàn)了,當(dāng)添加了 @JsonIgnore 這個(gè)屬性之后
執(zhí)行請(qǐng)求 /user/findById?id=1,控制臺(tái)打印如下:
Hibernate:
select
user0_.id as id1_2_0_,
user0_.age as age2_2_0_,
user0_.name as name3_2_0_
from
user user0_
where
user0_.id=?
[nio-7777-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [INTEGER] - [1]
只取進(jìn)行用戶信息的查詢,那我的 house 怎么辦呢?別急,我會(huì)給你們找回來(lái)的!
User 的 control 層
@GetMapping("findById")
public Optional<User> findById(int id){
Optional<User> users = userService.findById(id);
users.get().getHouse().forEach(v->{
System.out.println(v.getId() + "-"+ v.getAddr());
});
return userService.findById(id);
}
執(zhí)行請(qǐng)求 /user/findById?id=1,控制臺(tái)打印如下:
Hibernate:
select
house0_.user_id as user_id3_1_0_,
house0_.id as id1_1_0_,
house0_.id as id1_1_1_,
house0_.addr as addr2_1_1_,
house0_.user_id as user_id3_1_1_
from
house house0_
where
house0_.user_id=?
[nio-7777-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [INTEGER] - [1]
1-南京
2-蘇州
3-無(wú)錫以上就是Spring JPA聯(lián)表查詢之OneToMany源碼解析的詳細(xì)內(nèi)容,更多關(guān)于Spring JPA聯(lián)表查詢OneToMany的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java利用Jackson序列化實(shí)現(xiàn)數(shù)據(jù)脫敏詳解
在項(xiàng)目中有些敏感信息不能直接展示,比如客戶手機(jī)號(hào)、身份證、車牌號(hào)等信息,展示時(shí)均需要進(jìn)行數(shù)據(jù)脫敏,防止泄露客戶隱私。本文將利用Jackson序列化實(shí)現(xiàn)數(shù)據(jù)脫敏,需要的可以參考一下2023-03-03
Spring(AbstractRoutingDataSource)實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換示例
本篇文章主要介紹了詳解Spring(AbstractRoutingDataSource)實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02
解決Java處理HTTP請(qǐng)求超時(shí)的問(wèn)題
這篇文章主要介紹了解決Java處理HTTP請(qǐng)求超時(shí)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03
java實(shí)現(xiàn)支付寶支付接口的調(diào)用
本文主要介紹了java實(shí)現(xiàn)支付寶支付接口的調(diào)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07

