mybatis批量插入,批量更新以及null值問(wèn)題的解決
前言
mybatis批量插入、批量更新常規(guī)寫法,及升級(jí)寫法
null value in column “xxx” violates not-null constraint mybatis批量操作報(bào)錯(cuò)問(wèn)題處理。
批量插入
常規(guī)寫法:
<insert id="insertUser" parameterType="com.test.UserEntity"> insert into t_com_user(user_name, age, gender) values <foreach collection ="list" item="item" index="index" open="(" close= ")" separator= "),("> #{item.userName, jdbcType=VARCHAR}, #{item.age, jdbcType=INTEGER}, #{item.gender, jdbcType=INTEGER} </foreach> </insert>
假如我們?cè)谂坎迦霐?shù)據(jù)的時(shí)候,還想做一下關(guān)聯(lián)查詢,該怎么辦?
如下寫法,免去了先查詢數(shù)據(jù),然后遍歷list賦值,再批量插入的操作
<insert id="insertUser" parameterType="com.test.UserEntity"> insert into t_com_user(user_name, age, gender, dept_name) select t1.user_name, t1.age, t1.gender, t2.dept_name from ( VALUES <foreach collection ="list" item="item" index="index" open="(" close= ")" separator= "),("> #{item.userName, jdbcType=VARCHAR}, #{item.age, jdbcType=INTEGER}, #{item.gender, jdbcType=INTEGER}, #{item.deptId, jdbcType=INTEGER} </foreach> ) as t1 (user_name, age, gender, dept_id) left_join t_com_dept t2 on t1.dept_id = t2.id </insert>
批量更新
常規(guī)寫法
這種寫法實(shí)際執(zhí)行過(guò)程是單條執(zhí)行,即使使用的是id查找數(shù)據(jù),但是效率較差。
<update id="updateUser" parameterType="com.test.UserEntity"> <foreach collection ="list" item="item" index="index" separator= ";"> update t_com_user set user_name = #{item.userName, jdbcType=VARCHAR}, age = #{item.age, jdbcType=INTEGER}, gender = #{item.gender, jdbcType=INTEGER} where id = #{item.id, jdbcType=INTEGER} </foreach> </update>
升級(jí)寫法:參考批量插入操作,使用連表更新的語(yǔ)法
<update id="updateUser" parameterType="com.test.UserEntity"> update t_com_user t1 set user_name = t2.user_name, age = t2.age, gender = t2.gender from ( values <foreach collection ="list" item="item" index="index" open="(" close= ")" separator= "),("> #{item.id, jdbcType=INTEGER}, #{item.userName, jdbcType=VARCHAR}, #{item.age, jdbcType=INTEGER}, #{item.gender, jdbcType=INTEGER} </foreach> ) as t2 (id, user_name, age, gender) where t1.id = t2.id </update>
ERROR: null value in column “user_name” violates not-null constraint mybatis 批量操作報(bào)錯(cuò)問(wèn)題處理
mybatis的批量操作過(guò)程,傳入的list對(duì)象集合中,對(duì)象的某個(gè)屬性難免會(huì)為null,如果數(shù)據(jù)庫(kù)表該列恰好有not-null限制,則會(huì)報(bào)錯(cuò);
處理辦法,本文以pgsql的批量更新為例,親測(cè)可行:
方法一:使用
COALESCE(#{item.userName, jdbcType=VARCHAR}, ‘默認(rèn)名稱')
方式二:
user_name = COALESCE(t2.user_name, ‘默認(rèn)名稱')
二選一即可
<update id="updateUser" parameterType="com.test.UserEntity"> update t_com_user t1 set user_name = COALESCE(t2.user_name, '默認(rèn)名稱'), age = t2.age, gender = t2.gender from ( values <foreach collection ="list" item="item" index="index" open="(" close= ")" separator= "),("> #{item.id, jdbcType=INTEGER}, COALESCE(#{item.userName, jdbcType=VARCHAR}, '默認(rèn)名稱'), #{item.age, jdbcType=INTEGER}, #{item.gender, jdbcType=INTEGER} </foreach> ) as t2 (id, user_name, age, gender) where t1.id = t2.id </update>
mysql 使用IFNULL函數(shù) pgsql 使用COALESCE函數(shù)
方法二:
在foreach中使用if標(biāo)簽判斷
<if test= "item.userName != null"> #{item.userName, jdbcType=VARCHAR} </if> <if test= "item.userName == null"> '默認(rèn)名稱' </if>
Oracle mysql下,不支持 from (value (),()) as t 的寫法;可以參考
select * from ( select 1, '張三' from dual union select 2, '李四' from dual ) t
null 原因
當(dāng)mybatis做批量插入時(shí),插入的字段可能沒(méi)值,此時(shí)不做處理的話,mybatis會(huì)報(bào)異常,執(zhí)行失敗
根據(jù)mybatis的官網(wǎng)介紹,此時(shí)需要添加對(duì)應(yīng)的jdbcType類型映射,以處理null值 ,具體的映射關(guān)系參考:jdbc映射關(guān)系表
此時(shí),在所有可能為空的字段取值中添加jdbcType=XXX(一般全部添加即可)
案例
1.使用union all 來(lái)串連每個(gè)values,其中jdbcType的設(shè)置可以使null值也輸入進(jìn)去
<insert id="saveList" parameterType="java.util.List"> INSERT INTO DDZHPT.CMS_SCHEDUAL_DETIAL ( DEPT_ID, SCHEDUAL_DATE, CMS_SCHEDUAL_TYPE_ID, CMS_SCHEDUAL_TEAM_ID, CMS_SCHEDUAL_TYPE_PERIOD_ID, CMS_SCHEDUAL_TIME_ID, SYS_POST_ID, POINT_ID, PERSON_ID ) <foreach collection="list" item="item" index="index" separator="union all"> SELECT #{item.deptId,jdbcType=DECIMAL}, #{item.schedualDate,jdbcType=TIMESTAMP}, #{item.cmsSchedualTypeId,jdbcType=VARCHAR}, #{item.cmsSchedualTeamId,jdbcType=VARCHAR}, #{item.cmsSchedualTypePeriodId,jdbcType=VARCHAR}, #{item.cmsSchedualTimeId,jdbcType=VARCHAR}, #{item.sysPostId,jdbcType=VARCHAR}, #{item.pointId,jdbcType=VARCHAR}, #{item.personId,jdbcType=VARCHAR} FROM DUAL </foreach> </insert>
2.純粹使用foreach
<insert id="saveList" parameterType="java.util.List"> <foreach collection="list" item="item" index="index" separator="union all"> INSERT INTO DDZHPT.CMS_SCHEDUAL_DETIAL ( DEPT_ID, SCHEDUAL_DATE, CMS_SCHEDUAL_TYPE_ID, CMS_SCHEDUAL_TEAM_ID, CMS_SCHEDUAL_TYPE_PERIOD_ID, CMS_SCHEDUAL_TIME_ID, SYS_POST_ID, POINT_ID, PERSON_ID )VALUES( #{item.deptId,jdbcType=DECIMAL}, #{item.schedualDate,jdbcType=TIMESTAMP}, #{item.cmsSchedualTypeId,jdbcType=VARCHAR}, #{item.cmsSchedualTeamId,jdbcType=VARCHAR}, #{item.cmsSchedualTypePeriodId,jdbcType=VARCHAR}, #{item.cmsSchedualTimeId,jdbcType=VARCHAR}, #{item.sysPostId,jdbcType=VARCHAR}, #{item.pointId,jdbcType=VARCHAR}, #{item.personId,jdbcType=VARCHAR} ) </foreach> </insert>
推薦使用第一種方式,數(shù)據(jù)庫(kù)語(yǔ)句只有一條,減少數(shù)據(jù)庫(kù)執(zhí)行語(yǔ)句的負(fù)擔(dān)
3.union與union all區(qū)別
<!--插入所有列清單--> <sql id="insertAllCol"> <trim prefix="(" suffix=")" suffixOverrides=","> FPH, EFFECTIVE_TAX_AMOUNT, PURCHASER_TAXNO, INVOICE_STATE, DEDUCTIBLE_MODE, AMOUNT, OVERDUE_CHECK_MARK, ABNORMAL_TYPE, NSRSBH, ANTI_FAKE_CODE, UPDATE_TIME, DEDUCTIBLE_PERIOD, AGENCY_DRAWBACK, RESALE_CERTIFICATE_NUMBER, INVOICE_NO, CREATE_TIME, INV_ISSUE_DATE, TAX, AUDIT_STATE, DEDUCTIBLE_TYPE, DEDUCTIBLE_DATE, MANAGEMENT_STATUS, SALES_TAXNAME, DEDUCTIBLE_STATE, FLOW_ID, INVOICE_CATAGORY, SALES_TAXNO, INVOICE_CODE, ORIGINAL_PERIOD, INFO_SOURCES, </trim> </sql> <sql id="insertAllValueWithItem" databaseId="oracle"> <trim prefix=" SELECT " suffix=" FROM dual " suffixOverrides=","> #{item.fph,jdbcType=VARCHAR}, #{item.effectiveTaxAmount,jdbcType=NUMERIC}, #{item.purchaserTaxno,jdbcType=VARCHAR}, #{item.invoiceState,jdbcType=DATE}, #{item.deductibleMode,jdbcType=VARCHAR}, #{item.amount,jdbcType=NUMERIC}, #{item.overdueCheckMark,jdbcType=VARCHAR}, #{item.abnormalType,jdbcType=VARCHAR}, #{item.nsrsbh,jdbcType=VARCHAR}, #{item.antiFakeCode,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=DATE}, #{item.deductiblePeriod,jdbcType=VARCHAR}, #{item.agencyDrawback,jdbcType=VARCHAR}, #{item.resaleCertificateNumber,jdbcType=VARCHAR}, #{item.invoiceNo,jdbcType=VARCHAR}, #{item.createTime,jdbcType=DATE}, #{item.invIssueDate,jdbcType=VARCHAR}, #{item.tax,jdbcType=NUMERIC}, #{item.auditState,jdbcType=NUMERIC}, #{item.deductibleType,jdbcType=VARCHAR}, #{item.deductibleDate,jdbcType=VARCHAR}, #{item.managementStatus,jdbcType=VARCHAR}, #{item.salesTaxname,jdbcType=VARCHAR}, #{item.deductibleState,jdbcType=VARCHAR}, #{item.flowId,jdbcType=NUMERIC}, #{item.invoiceCatagory,jdbcType=VARCHAR}, #{item.salesTaxno,jdbcType=VARCHAR}, #{item.invoiceCode,jdbcType=VARCHAR}, #{item.originalPeriod,jdbcType=VARCHAR}, #{item.infoSources,jdbcType=VARCHAR}, </trim> </sql>
注:union all和union的區(qū)別
union all連接查詢,結(jié)果不去重
union做連接查詢結(jié)果去重
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot配置文件bootstrap和application區(qū)別及說(shuō)明
這篇文章主要介紹了SpringBoot配置文件bootstrap和application區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06Java使用雙異步實(shí)現(xiàn)將Excel的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫(kù)
在開發(fā)中,我們經(jīng)常會(huì)遇到這樣的需求,將Excel的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫(kù)中,這篇文章主要來(lái)和大家講講Java如何使用雙異步實(shí)現(xiàn)將Excel的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫(kù),感興趣的可以了解下2024-01-01Java讀取properties配置文件時(shí),出現(xiàn)中文亂碼的解決方法
下面小編就為大家?guī)?lái)一篇Java讀取properties配置文件時(shí),出現(xiàn)中文亂碼的解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11Java開發(fā)中的23種設(shè)計(jì)模式詳解(推薦)
本篇文章主要介紹了Java開發(fā)中的23種設(shè)計(jì)模式詳解,現(xiàn)在分享給大家,也給大家做個(gè)參考。感興趣的小伙伴們可以參考一下。 設(shè)計(jì)模式(Design Patterns)2016-11-11使用Java編寫一個(gè)簡(jiǎn)單的Web的監(jiān)控系統(tǒng)
這篇文章主要介紹了使用Java編寫一個(gè)簡(jiǎn)單的Web的監(jiān)控系統(tǒng)的例子,并且將重要信息轉(zhuǎn)為XML通過(guò)網(wǎng)頁(yè)前端顯示,非常之實(shí)用,需要的朋友可以參考下2015-11-11