最近項目開發是遇到了原來遇到的問題,給忘了,又在網上查詢了一次,這次在這里記錄下來
我這里采用的是最通用的批量更新(為了方便閱讀刪除了一些字段)
代碼
<update id="updateBatch" parameterType="java.util.List" > <foreach collection="list" item="item" index="index" open="" close="" separator=";"> update purchase_order_detail <set > <if test='item.consumeCode !=null and item.consumeCode !=""' >consumeCode = #{item.consumeCode},</if> <if test='item.consumeName !=null and item.consumeName !=""' >consumeName = #{item.consumeName},</if> <if test='item.productId !=null and item.productId !=""' >productId = #{item.productId},</if> </set> WHERE purchaseOrderDetailId = #{item.purchaseOrderDetailId} </foreach> </update>
注意實體屬性前一定要加對應的item——對應的顏色加深的地方,否側會報錯說參數不存在
然而在執行時一直報錯,當時沒太認真分析,只是通過后台代碼個各種情況調試時發現,一條數據的更新是可以的,但是多條就不行也就是傳入的參數list的size大於1時是無法執行的;
感覺問題逐漸清晰,然后就出網上查了一下,可能是問題描述不夠清晰,網上有一些其他的批量更新語句
像這樣的更新值相同的
<update id="updateStatus"> UPDATE purchase_order_detail set status= #{status} WHERE id in <foreach collection="ids" index="index" item="id" separator="," open="(" close=")"> #{id} </foreach> </update>
還有這樣的
<update id="updateListByHouseId" parameterType="java.util.ArrayList"> <foreach close=";" collection="list" index="index" item="item" open="" separator=";"> update rba_house_status <trim prefix="set" suffixOverrides=","> last_push_time = now(), <if test="item.pushStatus != null">push_status = #{item.pushStatus},</if> <if test="item.createStatus != null">create_status = #{item.createStatus},</if> <if test="item.houseCreateTime != null">house_create_time = #{item.houseCreateTime},</if> <if test="item.updateStatus != null">update_status = #{item.updateStatus},</if> update_time = now(), <if test="item.auditStatus != null">audit_status = #{item.auditStatus},</if> <if test="item.auditDesc != null">audit_desc = #{item.auditDesc},</if> <if test="item.hotelId != null">hotel_id = #{item.hotelId},</if> </trim> <where>house_id = #{item.houseId}</where> </foreach> </update>
看着就感覺易讀性較差;還是想用第一種批量更新,然后查了一下相關資料,其中說到mysql需要開啟支持批量執行sql語句——————也就是以這種 “;” 隔開的sql語句在批量執行時需要添加msyql 支持
在數據庫連接串后面添加
allowMultiQueries=true
例如
url: jdbc:mysql://127.0.0.1:3306/clouddo?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
拓展:此時本人就思考問什么沒有加入支持時第二種那樣的局部循環條件就可以執行呢,包括一些局部循環的插入語句
<insert id="insertBatch"> INSERT INTO purchase_order( purchaseOrderId, purchaseOrderNo, purchaseOrderName, purchaseApplyNo, purchaseOrderType, purchaseOrderTypeName, supplierId, supplierName, hosptialId, hosptialName, purchaseOrderAmount, purchaseOrderStatus, purchaseOrderDate, shippingAddress, shippingPerson, shippingPhone ) VALUES <foreach collection ="list" item="purchaseOrder" separator =","> ( #{purchaseOrder.purchaseOrderId}, #{purchaseOrder.purchaseOrderNo}, #{purchaseOrder.purchaseOrderName}, #{purchaseOrder.purchaseApplyNo}, #{purchaseOrder.purchaseOrderType}, #{purchaseOrder.purchaseOrderTypeName}, #{purchaseOrder.supplierId}, #{purchaseOrder.supplierName}, #{purchaseOrder.hosptialId}, #{purchaseOrder.hosptialName}, #{purchaseOrder.purchaseOrderAmount}, #{purchaseOrder.purchaseOrderStatus}, #{purchaseOrder.purchaseOrderDate}, #{purchaseOrder.shippingAddress}, #{purchaseOrder.shippingPerson}, #{purchaseOrder.shippingPhone} ) </foreach> </insert>
抱着試一試的心態我在后台將sql打印了出來
INSERT INTO distribution_order_detail ( distributionOrderNo, distributionOrderDetailNo, purchaseOrderNo, purchaseOrderDetailNo, consumeCode, ) VALUES ( ?, ?, ?, ?, ? ), ( ?, ?, ?, ?, ? )
此時發現這是后的sql語句雖然達到了批量的目的但是只是一條語句 而第一種批量跟新的sql語句卻是兩條sql 語句只是用“;”隔開了
update purchase_order_detail SET waitDistributionCount = ? WHERE purchaseOrderDetailId = ? ;
update purchase_order_detail SET waitDistributionCount = ? WHERE purchaseOrderDetailId = ?
第二種修改值相同的批量更新就更是一條sql了
UPDATE consume_material SET consumeStatus = ? WHERE consumeId in ( ? , ? )
這里再記錄說明一下我遇到的其他問題
在mybaits 中針對時間的字段進行判斷時
<if test='sterilizationExpirationDate !=null and sterilizationExpirationDate !=""' >sterilizationExpirationDate = #{sterilizationExpirationDate},</if>
報錯
invalid comparison: java.sql.Timestamp and java.lang.String
錯誤的原因是
mybatis 3.3.0中對於時間參數進行比較有的一個bug. 如果拿傳入的時間類型參數與空字符串”進行對比判斷則會引發異常. 所以在上面的代碼中去該該判斷, 只保留非空判斷就正常了
修改后
<if test='sterilizationExpirationDate !=null ' >sterilizationExpirationDate = #{sterilizationExpirationDate},</if>
這樣就可以了
以上僅是個人理解並作為記錄,不對之處希望各位幫忙指正一下。