0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

MybatisPlus使用 saveOrUpdate方法踩坑記錄

jf_ro2CN3Fa ? 來(lái)源:芋道源碼 ? 作者:芋道源碼 ? 2022-11-02 16:25 ? 次閱讀

慎用!

UpdateWrapper 小貼士

后續(xù)

今天的想法是,要在插入數(shù)據(jù)庫(kù)時(shí),如果有某某一個(gè)主要字段的值重復(fù),則不插入,否則則插入!看了一下mybatis-Plus是有這個(gè)saveOrUpdate 方法!

原本使用save時(shí)是沒(méi)有問(wèn)題了,改成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í)體類(lèi)的主鍵頭上,打個(gè)@TableId,如下,后面是對(duì)應(yīng)數(shù)據(jù)庫(kù)的字段,已經(jīng)主鍵自動(dòng)遞增。

@Data
@AllArgsConstructor
@NoArgsConstructor
publicclassSubject{

@TableId(value="subject_Code",type=IdType.AUTO)
privatelongsubjectCode;

privateStringsubjectNameCn;

privateStringsubjectNameEn;

privateStringsubjectHref;

privatelongsubjectParentCode;

privatelonglevelCode;

privateintisDelete;

privatelongoperateTimestamp;


}

不過(guò)還有個(gè)問(wèn)題,就是這個(gè)是根據(jù)主鍵做操作的,但是我主鍵本來(lái)就是自動(dòng)遞增肯定不會(huì)有問(wèn)題的,接下來(lái)就是想個(gè)辦法,讓他根據(jù)指定字段做操作,好像是有提供了一個(gè)口子。

//根據(jù)updateWrapper嘗試更新,否繼續(xù)執(zhí)行saveOrUpdate(T)方法
booleansaveOrUpdate(Tentity,WrapperupdateWrapper);

我再去看一下怎么操作的!

研究嘗試了半天,終于搞出來(lái)了,可能是很少有人會(huì)像我這樣做吧!所以我自己嘗試了下。

當(dāng)saveOrUpdate不使用條件構(gòu)造器時(shí),會(huì)先做根據(jù)主鍵查詢(xún),如果查出來(lái)的結(jié)果為0,那么就執(zhí)行插入操作,如果查出來(lái)的結(jié)果不為0,則執(zhí)行更新操作。

但是一般情況下,主鍵都不會(huì)重復(fù)啊!所有我就用條件構(gòu)造器Wrapper!

UpdateWrappersubject_name_cn=newUpdateWrapper()
.eq("subject_Name_Cn",subjectNameCn);
subjectService.saveOrUpdate(subject,subject_name_cn);

這樣改變后的結(jié)果就是會(huì)先執(zhí)行修改,如果執(zhí)行一條,則執(zhí)行成功,如果執(zhí)行結(jié)果為0,再執(zhí)行根據(jù)主鍵查詢(xún),然后做插入操作!

其實(shí)有點(diǎn)多此一舉的感覺(jué),因?yàn)榧热欢家呀?jīng)更新不到結(jié)果了,那么肯定是沒(méi)有這個(gè)字段咯!

不過(guò)轉(zhuǎn)念一想,你是指定字段沒(méi)有,又不是主鍵沒(méi)有!

但是主鍵自增那肯定沒(méi)有?。?/p>

所有我又想到一個(gè)騷操作,我不傳UpdateWrapper而傳QueryWrapper會(huì)怎么樣呢!

會(huì)不會(huì)加在查詢(xún)條件種呢!我丟進(jìn)去沒(méi)有報(bào)錯(cuò),有點(diǎn)小激動(dòng),不知道結(jié)果如何!

QueryWrappersubject_name_cn1=newQueryWrapper()
.eq("subject_Name_Cn",subjectNameCn);
subjectService.saveOrUpdate(subject,subject_name_cn1);

好吧!上來(lái)全給我Update了!絲毫不留情面!我把數(shù)據(jù)刪了再試試!

好吧!然并卵!幻想破滅!跟傳UpdateWrapper沒(méi)有區(qū)別!~告辭!

看了一下源碼,默認(rèn)參數(shù)是Wrapper類(lèi)型,然后根據(jù)條件構(gòu)造器更新,成功則返回,不成功則走無(wú)條件構(gòu)造器的方法。

defaultbooleansaveOrUpdate(Tentity,WrapperupdateWrapper){
returnthis.update(entity,updateWrapper)||this.saveOrUpdate(entity);
}

我感覺(jué)應(yīng)該加個(gè)類(lèi)型判斷!

if(updateWrapperinstanceofQueryWrapper){
//去拼接查詢(xún)語(yǔ)句!
}
if(updateWrapperinstanceofUpdateWrapper){
//去拼接更新語(yǔ)句!
}

這樣就不會(huì)只根據(jù)ID來(lái)死查了!

為什么要用updateWrapper?

它與queryWrapper的區(qū)別就是:updateWrapper用set來(lái)設(shè)置修改的數(shù)據(jù);queryWrapper應(yīng)用select來(lái)設(shè)置要查出來(lái)的數(shù)據(jù)。

saveOrUpdate 是否有映射id

我們知道m(xù)ybatis在插入時(shí),會(huì)映射id,但是如果是saveOrUpdate會(huì)怎么樣呢?

比如我saveOrUpdate()后,需要用他的id,但是我傳進(jìn)去的對(duì)象是沒(méi)有id的。

@Test
voidsaveOrUpdate(){
UserTextuserText=newUserText();
userText.setUserSex(Sex.MAN);
booleanb=userTextService.saveOrUpdate(userText);
System.out.println(userText.getUserId());
}

可以看到他先通過(guò)id查了沒(méi)有再進(jìn)行插入,然后返回新的id。

==>Preparing:SELECTuser_id,user_name,user_sex,start_timeFROMuser_textWHEREuser_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:INSERTINTOuser_text(user_sex)VALUES(?)
==>Parameters:1(Integer)
<==????Updates:?1

不過(guò)這個(gè)update,不用試我都感覺(jué)難搞,因?yàn)槟闳绻麤](méi)有id,那么你傳入這個(gè)對(duì)象的值,可能查出多個(gè)對(duì)象,那么他要把哪個(gè)id映射回來(lái),是吧!

@Test
voidsaveOrUpdate(){
UserTextuserText=newUserText();
userText.setUserSex(Sex.MAN);
UpdateWrapperobjectUpdateWrapper=newUpdateWrapper()
.eq("user_sex",Sex.MAN);
booleanb=userTextService.saveOrUpdate(userText,objectUpdateWrapper);
System.out.println(userText.getUserId());
}

但還是試一下,當(dāng)我們加了一個(gè)UpdateWrapper后,有執(zhí)行成功,執(zhí)行了3條,返回了id為0。

但是這次加了wrapper,我再試試如果只插入一條,會(huì)怎么樣。哈哈,不去讀源碼去debug,就只能這樣試試了,莫怪。

誒,對(duì)啊,我去看看源碼先,看能不能看出什么門(mén)道。

之前好像也有看了點(diǎn)源碼。兩種不同構(gòu)造的方法,執(zhí)行的邏輯也不一樣。

booleansaveOrUpdate(Tentity);

defaultbooleansaveOrUpdate(Tentity,WrapperupdateWrapper){
returnthis.update(entity,updateWrapper)||this.saveOrUpdate(entity);
}

區(qū)別不大,就是會(huì)多執(zhí)行一步更新,如果執(zhí)行成功就直接走,執(zhí)行不成功再根據(jù)這個(gè)對(duì)象做saveOrUpdate。

進(jìn)去翻了翻就是,如果通過(guò)id查到值,就根據(jù)id更新,不然就做新增。

所以也就不用試了,還是自己手寫(xiě)一個(gè)吧,如果需要返回id的話(huà)。

慎用!

細(xì)思極恐,當(dāng)你是主鍵自動(dòng)生成的數(shù)據(jù),一定要寫(xiě)UpdateWrapper,不然你必然是一直插入!完全不會(huì)更新,因?yàn)槟J(rèn)是用id查詢(xún)的。

而主鍵生成的數(shù)據(jù),一般都不會(huì)去寫(xiě)一個(gè)id,所以?。≮s快看看吧!

基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項(xiàng)目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro

視頻教程:https://doc.iocoder.cn/video/

UpdateWrapper 小貼士

上面雖然寫(xiě)了updateWrapper可以寫(xiě)一個(gè)set屬性,有兩種情況。

首先,我們一個(gè)對(duì)象,有5條屬性,只有4條有值,1條沒(méi)有值。

mybatis-plus在執(zhí)行時(shí),會(huì)先去看看你的對(duì)象哪條屬性有值,哪條沒(méi)有。

只會(huì)更新有值的屬性,所以只會(huì)更新4個(gè)屬性,另外一個(gè)屬性并不會(huì)把他置空。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項(xiàng)目地址:https://gitee.com/zhijiantianya/yudao-cloud

視頻教程:https://doc.iocoder.cn/video/

后續(xù)

我發(fā)現(xiàn)一個(gè)很垃圾的,前面我吹的那個(gè)updateWrapper的set多牛逼,其實(shí)是我想的太美了,他只是在原本的基礎(chǔ)上再加一個(gè)字段!我吐了!

UpdateWrapperupdateWrapper=newUpdateWrapper()
.eq("game_id",gameScorePo.getGameId())
.eq("team_id",gameScorePo.getTeamId())
.eq("quarter",gameScorePo.getQuarter())
.set("score",gameScorePo.getScore());

gameScoreService.saveOrUpdate(gameScorePo,updateWrapper);

這樣的執(zhí)行結(jié)果是這樣的!

3be000f6-573d-11ed-a3b6-dac502259ad0.png

兩個(gè)score,我吐了!

難道是我打開(kāi)的姿勢(shì)不對(duì)?

查了一下知道這個(gè)set怎么樣了

3c03605a-573d-11ed-a3b6-dac502259ad0.png

就是不要丟對(duì)象,丟一個(gè)空的對(duì)象,這樣就能set了!

單獨(dú)的set好用,但是用在saveOrUpdate就不好用咯!看自己的需求走吧!

審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)庫(kù)
    +關(guān)注

    關(guān)注

    7

    文章

    3739

    瀏覽量

    64177
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    630

    瀏覽量

    29077

原文標(biāo)題:MybatisPlus 使用 saveOrUpdate() 方法踩坑記錄(慎用)

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【STM32+機(jī)智云】機(jī)智云手機(jī)APP點(diǎn)燈實(shí)驗(yàn)記錄 精選資料分享

    【STM32+機(jī)智云】機(jī)智云手機(jī)APP點(diǎn)燈實(shí)驗(yàn)記錄一、實(shí)驗(yàn)背景因?yàn)轫?xiàng)目開(kāi)發(fā)需要用到云平臺(tái),所以開(kāi)始學(xué)習(xí)機(jī)智云平臺(tái),聽(tīng)說(shuō)機(jī)智云比較容易入門(mén),還有手機(jī)APP。因此開(kāi)始了
    發(fā)表于 08-04 08:30

    開(kāi)發(fā)STM32 USB HID過(guò)的

    記錄一下 開(kāi)發(fā)STM32 USB HID過(guò)的一、前言二、代碼配置一、前言MCU: STM32F103C8T6CubeMX: STM32CubeMX 5.3.0二、代碼配置引腳配置時(shí)鐘樹(shù)配置我
    發(fā)表于 08-24 07:15

    使用樹(shù)莓派搭建stm32開(kāi)發(fā)環(huán)境過(guò)的以及碰到的問(wèn)題

    使用樹(shù)莓派搭建stm32開(kāi)發(fā)環(huán)境了很多,下面主要是記錄一下過(guò)的,以及碰到的問(wèn)題。##開(kāi)發(fā)方式的選擇1.使用Eclipse+GDB+O
    發(fā)表于 08-24 07:47

    NodeMCU開(kāi)發(fā)板經(jīng)歷分享

    寫(xiě)在前面今天入手了一個(gè)NodeMCU的板子,準(zhǔn)備學(xué)習(xí)一下物聯(lián)網(wǎng)相關(guān)的知識(shí)。不過(guò)由于博主學(xué)藝不精,在第一步燒寫(xiě)固件上就了,所以就想著把自己的經(jīng)歷寫(xiě)出來(lái)分享給大家,希望能有一些幫助
    發(fā)表于 11-01 07:55

    Linux學(xué)習(xí)過(guò)程過(guò)的與如何解決

    Linux記錄記錄Linux學(xué)習(xí)過(guò)程過(guò)的與如何解決
    發(fā)表于 11-04 08:44

    STM32編程常有哪些?

    STM32編程常有哪些?
    發(fā)表于 12-17 06:15

    Xavier入門(mén)PWM問(wèn)題解決方法

    Xavier入門(mén)PWM問(wèn)題解決方法GPIO問(wèn)題解決方法PWM問(wèn)題由于需要做外部傳感器的觸發(fā)同步,所以需要一個(gè)方波,考慮用Xavier的PWM,結(jié)果折騰了好久發(fā)現(xiàn)需要配置內(nèi)部硬件,折
    發(fā)表于 01-10 08:11

    記錄寫(xiě)SAM4S的bootloader所

    記錄寫(xiě)SAM4S的bootloader所
    發(fā)表于 01-24 07:16

    關(guān)于RK1808板子調(diào)試過(guò)程過(guò)的記錄

    關(guān)于RK1808板子調(diào)試過(guò)程過(guò)的記錄
    發(fā)表于 02-16 06:38

    STM32H7+UCOSIII+LWIP記錄相關(guān)資料推薦

    STM32H7+UCOSIII+LWIP記錄主要功能:?jiǎn)纹瑱C(jī)作TCP服務(wù)器實(shí)現(xiàn)PC端多客戶(hù)端連接單片機(jī),并發(fā)傳輸數(shù)據(jù)。點(diǎn)1、優(yōu)先級(jí)問(wèn)題:一個(gè)客戶(hù)端連接就創(chuàng)建一個(gè)線程,優(yōu)先級(jí)由高到
    發(fā)表于 02-18 06:30

    嵌入式Linux記錄

    Linux記錄記錄Linux學(xué)習(xí)過(guò)程過(guò)的與如何解決
    發(fā)表于 11-01 17:21 ?10次下載
    嵌入式Linux<b class='flag-5'>踩</b><b class='flag-5'>坑</b><b class='flag-5'>記錄</b>

    STM32CubeIDE+FREERTOS記錄

    STM32CubeIDE+FREERTOS記錄
    發(fā)表于 12-05 18:06 ?15次下載
    STM32CubeIDE+FREERTOS<b class='flag-5'>踩</b><b class='flag-5'>坑</b><b class='flag-5'>記錄</b>

    STM32H7+UCOSIII+LWIP記錄

    STM32H7+UCOSIII+LWIP記錄主要功能:?jiǎn)纹瑱C(jī)作TCP服務(wù)器實(shí)現(xiàn)PC端多客戶(hù)端連接單片機(jī),并發(fā)傳輸數(shù)據(jù)。點(diǎn)1、優(yōu)先級(jí)問(wèn)題:一個(gè)客戶(hù)端連接就創(chuàng)建一個(gè)線程,優(yōu)先級(jí)由高到
    發(fā)表于 12-23 19:54 ?5次下載
    STM32H7+UCOSIII+LWIP<b class='flag-5'>踩</b><b class='flag-5'>坑</b><b class='flag-5'>記錄</b>

    推挽電路的,你過(guò)沒(méi)?

    推挽電路的,你過(guò)沒(méi)?
    的頭像 發(fā)表于 11-24 16:25 ?1000次閱讀
    推挽電路的<b class='flag-5'>坑</b>,你<b class='flag-5'>踩</b>過(guò)沒(méi)?

    反相輸入放大器的,你過(guò)沒(méi)有?

    反相輸入放大器的,你過(guò)沒(méi)有?
    的頭像 發(fā)表于 12-06 15:35 ?531次閱讀
    反相輸入放大器的<b class='flag-5'>坑</b>,你<b class='flag-5'>踩</b>過(guò)沒(méi)有?