相信大部分java小伙伴在日常開發(fā)過程中,在存儲操作層都會選擇更容易上手的jpa,各種封裝,通過注解等方式,簡化了大量的代碼內(nèi)容,同時提升了開發(fā)效率,但是(敲黑板,永遠都躲不開的但是...)相應(yīng)也將一些問題隱藏,需要更多的時間去理解、分析才能找到病根。
JPA簡介
JPA全稱(Java Persistence API),通常叫持久層API。它提供面向?qū)ο蟮?a target="_blank">編程模型,讓使用者更容易理解與上手;底層也提供了通用接口,可以實現(xiàn)與其它框架快速集成。下面整理一些基礎(chǔ)概念,不了解的可以參考下:
- JPA是一種ORM規(guī)范。
- Hibernate是JPA的一個子集。
- Spring Data JPA,是JPA的代碼實現(xiàn) ,同時底層為Hibernate技術(shù)實現(xiàn)。
JPA實戰(zhàn)-級聯(lián)操作
目前小編所開發(fā)項目的數(shù)據(jù)持久層大部分采用的是Spring Data JPA,經(jīng)過長時間的使用驗證,發(fā)現(xiàn)出了級聯(lián)保存問題,即調(diào)用repository的save方法后,發(fā)現(xiàn)數(shù)據(jù)結(jié)果卻是“丟三落四”,這就很讓人腦袋疼,下面結(jié)合代碼一起分析下
- 代碼場景:用戶與住址是多對多的關(guān)系,JPA中描述這種關(guān)系通常使用@ManyToMany注解,首先是創(chuàng)建對象
//維護端
public class User{
//屬性代碼省略
@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinTable(name = "user_addresses",
joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "user_id")},
inverseJoinColumns = {@JoinColumn(name = "address_id",referencedColumnName = "address_id")})
private Set< Address > addresses = new HashSet< >();
}
//被維護方
public class Address{
//屬性代碼省略
@ManyToMany(mappedBy = "addresses")
@JsonIgnore
private Set< User > users = new HashSet< >();
}
- 最初我只在維護端設(shè)置的級聯(lián)屬性(Cascade.ALL),然后通過維護端進行保存,很順利,User表、Address表、user_addresses關(guān)聯(lián)表都能保存,代碼如下,沒毛病。
// 維護端操作
public User save(){
Address address = new Address();
address.setAddressName("北京海淀");
User user1 = new User();
user1.setName("阿韋");
user1.getAddresses().add(address);
return UserService.save(User1);
}
- 然后我換了個思路,從被維護端能不能進行保存,然后就立即進行嘗試。代碼如下
// 被維護端操作
public Address save(){
Address address = new Address();
address.setAddressName("北京海淀");
User user1 = new User();
user1.setName("阿韋");
address.getUsers().add(user1);
return addressService.save(address);
}
- 結(jié)果,我以為能夠成功的時候,發(fā)現(xiàn)只保存了Address一張表,還沒報錯,就是User表和關(guān)聯(lián)表死活沒有數(shù)據(jù)。此時,問題已經(jīng)復(fù)現(xiàn),查閱各種文檔說明,大概是需要添加級聯(lián)屬性,改造內(nèi)容如下
@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER,mappedBy = "addresses")
private Set< User > users = new HashSet< >();
- 修改之后再一次進行保存,兩個實體類的表確實都生成了數(shù)據(jù),但是關(guān)聯(lián)表還是沒有,這時已經(jīng)快要抓狂,但問題還是沒解決,繼續(xù)耐心分析,很快就在控制臺打印sql處發(fā)現(xiàn)了一些貓膩:
- 果然是沒有對關(guān)聯(lián)表的數(shù)據(jù)操作,接下來又是一頓探索,終于找到根源了,由被維護端發(fā)起操作的時候,需要為關(guān)聯(lián)類屬性添加彼此,感覺真是關(guān)聯(lián)到“恩愛”的地步了,羨煞旁人啊!!!
// 被維護端操作
public Address save(){
Address address = new Address();
address.setAddressName("中央花園");
User user1 = new User();
user1.setName("阿韋");
user1.setHeight("170");
user1.setSex("1");
//在彼此定義對方類集合中添加
user1.getAddresses().add(address);
address.getUsers().add(user1);
return addressService.save(address);
}
- 最終徹底解決掉了問題,數(shù)據(jù)持久化到相應(yīng)的表中。自己也確實松了一口氣,過程雖然充滿曲折,但結(jié)果還是非常鼓舞自己的。
心得
希望本文能夠幫你避開jpa的坑,這就是小編最驕傲的事情。每一條道路上都是坑洼不平的,有些時候可能會掉入坑里,希望每個人都能重新站起來,跳過阻擋你的“坑”,最終會收獲到很多,讓自己變得更強。
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7247瀏覽量
91296 -
存儲
+關(guān)注
關(guān)注
13文章
4508瀏覽量
87150 -
API
+關(guān)注
關(guān)注
2文章
1565瀏覽量
63639 -
編程
+關(guān)注
關(guān)注
88文章
3686瀏覽量
94953
發(fā)布評論請先 登錄
JPA實體類中的注解介紹
ARM的概念
PWM的概念和產(chǎn)生原理
嵌入式數(shù)據(jù)庫驅(qū)動程序類相關(guān)資料分享
怎樣去設(shè)計一個基于springboot+freemark+jpa+MySQL的在線電影訂票系統(tǒng)
為什么會出現(xiàn)中斷的概念呢?這個概念是為了解決什么問題
一文詳談Spring JPA
基于概念可辨識矩陣的概念約簡方法

評論