Mybatis-Plus使用saveOrUpdate及問題解決方法
今天的想法是,要在插入數(shù)據(jù)庫(kù)時(shí),如果有某某一個(gè)主要字段的值重復(fù),則不插入,否則則插入!
看了一下mybatis-Plus是有這個(gè)saveOrUpdate 方法!
原本使用save時(shí)是沒有問題了,改成saveOrUpdate 用了一下就報(bào)錯(cuò)了。
com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: error: can not execute. because can not find column for id from entity!
就是這個(gè)mybatisPlus不能找到哪個(gè)是主鍵字段,因?yàn)檫@個(gè)saveOrUpdate默認(rèn)是根據(jù)主鍵執(zhí)行操作的!
所有需要在原本的實(shí)體類的主鍵頭上,打個(gè)@TableId,如下,后面是對(duì)應(yīng)數(shù)據(jù)庫(kù)的字段,已經(jīng)主鍵自動(dòng)遞增。
@Data @AllArgsConstructor @NoArgsConstructor public class Subject { @TableId(value = "subject_Code", type = IdType.AUTO) private long subjectCode; private String subjectNameCn; private String subjectNameEn; private String subjectHref; private long subjectParentCode; private long levelCode; private int isDelete; private long operateTimestamp; }
不過還有個(gè)問題,就是這個(gè)是根據(jù)主鍵做操作的,但是我主鍵本來就是自動(dòng)遞增肯定不會(huì)有問題的,接下來就是想個(gè)辦法,讓他根據(jù)指定字段做操作,好像是有提供了一個(gè)口子。
// 根據(jù)updateWrapper嘗試更新,否繼續(xù)執(zhí)行saveOrUpdate(T)方法 boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
我再去看一下怎么操作的!
研究嘗試了半天,終于搞出來了,可能是很少有人會(huì)像我這樣做吧!所以我自己嘗試了下。
當(dāng)saveOrUpdate不使用條件構(gòu)造器時(shí),會(huì)先做根據(jù)主鍵查詢,如果查出來的結(jié)果為0,那么就執(zhí)行插入操作,如果查出來的結(jié)果不為0,則執(zhí)行更新操作。
但是一般情況下,主鍵都不會(huì)重復(fù)??!所有我就用條件構(gòu)造器Wrapper!
UpdateWrapper<Subject> subject_name_cn = new UpdateWrapper<Subject>() .eq("subject_Name_Cn", subjectNameCn); subjectService.saveOrUpdate(subject,subject_name_cn );
這樣改變后的結(jié)果就是會(huì)先執(zhí)行修改,如果執(zhí)行一條,則執(zhí)行成功,如果執(zhí)行結(jié)果為0,再執(zhí)行根據(jù)主鍵查詢,然后做插入操作!
其實(shí)有點(diǎn)多此一舉的感覺,因?yàn)榧热欢家呀?jīng)更新不到結(jié)果了,那么肯定是沒有這個(gè)字段咯!
不過轉(zhuǎn)念一想,你是指定字段沒有,又不是主鍵沒有!
但是主鍵自增那肯定沒有??!
所有我又想到一個(gè)騷操作,我不傳UpdateWrapper而傳QueryWrapper會(huì)怎么樣呢!
會(huì)不會(huì)加在查詢條件種呢!我丟進(jìn)去沒有報(bào)錯(cuò),有點(diǎn)小激動(dòng),不知道結(jié)果如何!
QueryWrapper<Subject> subject_name_cn1 = new QueryWrapper<Subject>() .eq("subject_Name_Cn", subjectNameCn); subjectService.saveOrUpdate(subject,subject_name_cn1);
好吧!上來全給我Update了!絲毫不留情面!我把數(shù)據(jù)刪了再試試!
好吧!然并卵!幻想破滅!跟傳UpdateWrapper沒有區(qū)別!~告辭!
看了一下源碼,默認(rèn)參數(shù)是Wrapper類型,然后根據(jù)條件構(gòu)造器更新,
成功則返回,
不成功則走無條件構(gòu)造器的方法。
default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) { return this.update(entity, updateWrapper) || this.saveOrUpdate(entity); }
我感覺應(yīng)該加個(gè)類型判斷!
if(updateWrapper instanceof QueryWrapper){ 去拼接查詢語(yǔ)句! } if(updateWrapper instanceof UpdateWrapper){ 去拼接更新語(yǔ)句! }
這樣就不會(huì)只根據(jù)ID來死查了!
2021-05-21 11:07:24
我才終于明白~
為什么要用updateWrapper了!
它與queryWrapper的區(qū)別就是。
updateWrapper用set來設(shè)置修改的數(shù)據(jù)。
queryWrapper應(yīng)用select來設(shè)置要查出來的數(shù)據(jù)。
哈哈,這個(gè)還是很重要的!
saveOrUpdate 是否有映射id
我們知道m(xù)ybatis在插入時(shí),會(huì)映射id,但是如果是saveOrUpdate會(huì)怎么樣呢?
比如我saveOrUpdate()后,需要用他的id,但是我傳進(jìn)去的對(duì)象是沒有id的。
@Test void saveOrUpdate(){ UserText userText = new UserText(); userText.setUserSex(Sex.MAN); boolean b = userTextService.saveOrUpdate(userText); System.out.println(userText.getUserId()); }
可以看到他先通過id查了沒有再進(jìn)行插入,然后返回新的id。
==> Preparing: SELECT user_id,user_name,user_sex,start_time FROM user_text WHERE user_id=?
==> Parameters: 0(Long)
<== Total: 0
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6d0fe80c]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6d0fe80c] from current transaction
==> Preparing: INSERT INTO user_text ( user_sex ) VALUES ( ? )
==> Parameters: 1(Integer)
<== Updates: 1
不過這個(gè)update,不用試我都感覺難搞,因?yàn)槟闳绻麤]有id,那么你傳入這個(gè)對(duì)象的值,可能查出多個(gè)對(duì)象,那么他要把哪個(gè)id映射回來,是吧!
@Test void saveOrUpdate(){ UserText userText = new UserText(); userText.setUserSex(Sex.MAN); UpdateWrapper<UserText> objectUpdateWrapper = new UpdateWrapper<UserText>() .eq("user_sex",Sex.MAN); boolean b = userTextService.saveOrUpdate(userText,objectUpdateWrapper); System.out.println(userText.getUserId()); }
但還是試一下,當(dāng)我們加了一個(gè)UpdateWrapper后,有執(zhí)行成功,執(zhí)行了3條,返回了id為0。
但是這次加了wrapper,我再試試如果只插入一條,會(huì)怎么樣。哈哈,不去讀源碼去debug,就只能這樣試試了,莫怪。
誒,對(duì)啊,我去看看源碼先,看能不能看出什么門道。
之前好像也有看了點(diǎn)源碼。兩種不同構(gòu)造的方法,執(zhí)行的邏輯也不一樣。
boolean saveOrUpdate(T entity); default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) { return this.update(entity, updateWrapper) || this.saveOrUpdate(entity); }
區(qū)別不大,就是會(huì)多執(zhí)行一步更新,如果執(zhí)行成功就直接走,執(zhí)行不成功再根據(jù)這個(gè)對(duì)象做saveOrUpdate。
進(jìn)去翻了翻就是,如果通過id查到值,就根據(jù)id更新,不然就做新增。
所以也就不用試了,還是自己手寫一個(gè)吧,如果需要返回id的話。
慎用!
細(xì)思極恐,當(dāng)你是主鍵自動(dòng)生成的數(shù)據(jù),一定要寫UpdateWrapper,不然你必然是一直插入!完全不會(huì)更新,因?yàn)槟J(rèn)是用id查詢的。
而主鍵生成的數(shù)據(jù),一般都不會(huì)去寫一個(gè)id,所以?。≮s快看看吧!
UpdateWrapper 小貼士
上面雖然寫了updateWrapper可以寫一個(gè)set屬性,有兩種情況。
首先,我們一個(gè)對(duì)象,有5條屬性,只有4條有值,1條沒有值。
mybatis-plus在執(zhí)行時(shí),會(huì)先去看看你的對(duì)象哪條屬性有值,哪條沒有。
只會(huì)更新有值的屬性,所以只會(huì)更新4個(gè)屬性,另外一個(gè)屬性并不會(huì)把他置空。
如果你只想改一條屬性,也可以多寫一個(gè)set,不過感覺沒啥必要,不過比較靈活的就是。
你想寫另外一個(gè)值,就可以寫進(jìn)set里。
2021-05-21 13:31:32
我發(fā)現(xiàn)一個(gè)很垃圾的,前面我吹的那個(gè)updateWrapper的set多牛逼,其實(shí)是我想的太美了,他只是在原本的基礎(chǔ)上再加一個(gè)字段!我吐了!
UpdateWrapper<GameScorePo> updateWrapper = new UpdateWrapper<GameScorePo>() .eq("game_id",gameScorePo.getGameId()) .eq("team_id",gameScorePo.getTeamId()) .eq("quarter",gameScorePo.getQuarter()) .set("score",gameScorePo.getScore()); gameScoreService.saveOrUpdate(gameScorePo,updateWrapper);
這樣的執(zhí)行結(jié)果是這樣的!
兩個(gè)score,我吐了!
難道是我打開的姿勢(shì)不對(duì)?
查了一下知道這個(gè)set怎么樣了
就是不要丟對(duì)象,丟一個(gè)空的對(duì)象,這樣就能set了!
單獨(dú)的set好用,但是用在saveOrUpdate就不好用咯!看自己的需求走吧!
到此這篇關(guān)于Mybatis-Plus使用saveOrUpdate及問題解決方法的文章就介紹到這了,更多相關(guān)Mybatis-Plus saveOrUpdate內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳談cxf和axis兩種框架下的webservice客戶端開發(fā)
這篇文章主要介紹了詳談cxf和axis兩種框架下的webservice客戶端開發(fā),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08使用Spring特性實(shí)現(xiàn)接口多實(shí)現(xiàn)類的動(dòng)態(tài)調(diào)用方式
這篇文章主要介紹了使用Spring特性實(shí)現(xiàn)接口多實(shí)現(xiàn)類的動(dòng)態(tài)調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02springboot 中 druid+jpa+MYSQL數(shù)據(jù)庫(kù)配置過程
這篇文章主要介紹了springboot 中 druid+jpa+MYSQL數(shù)據(jù)庫(kù)配置,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08Java/Web調(diào)用Hadoop進(jìn)行MapReduce示例代碼
本篇文章主要介紹了Java/Web調(diào)用Hadoop進(jìn)行MapReduce示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11java實(shí)現(xiàn)簡(jiǎn)單解析XML文件功能示例
這篇文章主要介紹了java實(shí)現(xiàn)簡(jiǎn)單解析XML文件功能,結(jié)合實(shí)例形式分析了java針對(duì)xml文件的讀取、遍歷節(jié)點(diǎn)及輸出等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10SpringBoot實(shí)現(xiàn)EMQ設(shè)備的上下線告警
EMQX?的上下線系統(tǒng)消息通知功能在客戶端連接成功或者客戶端斷開連接,需要實(shí)現(xiàn)設(shè)備的上下線狀態(tài)監(jiān)控,所以本文給大家介紹了如何通過SpringBoot實(shí)現(xiàn)EMQ設(shè)備的上下線告警,文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-10-10IntelliJ IDEA中Project與Module的概念以及區(qū)別
這篇文章主要給大家介紹了關(guān)于IntelliJ IDEA中Project與Module的概念以及區(qū)別的相關(guān)資料,文中通過實(shí)例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Java SpringBoot快速集成SpringBootAdmin管控臺(tái)監(jiān)控服務(wù)詳解
這篇文章主要介紹了如何基于springboot-admin管控臺(tái)監(jiān)控服務(wù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-09-09