MyBatis MapperProvider MessageFormat拼接批量SQL語句執(zhí)行報(bào)錯(cuò)的原因分析及解決辦法
最近在項(xiàng)目中有這么一段代碼:下載服務(wù)器基礎(chǔ)業(yè)務(wù)數(shù)據(jù)進(jìn)行本地批量插入操作,因項(xiàng)目中使用mybatis進(jìn)行持久化操作,故直接考慮使用mybatis的批量插入功能。
1.以下是Mapper接口的部分代碼
public interface PrintMapper { @InsertProvider(type = PrintMapperProvider.class,method = "insertAllLotWithVehicleCode4H2") void insertAllLotWithVehicleCode(List<LotWithVehicleCodeBO> lotWithVehicleCodes); }
2.對(duì)應(yīng)MapperProvider中函數(shù)片段
public String insertAllLotWithVehicleCode4H2(Map<String,List<LotWithVehicleCodeBO>> map) { List<LotWithVehicleCodeBO> lotWithVehicleCodeBOs = map.get("list"); StringBuilder sb = new StringBuilder("INSERT INTO MTC_LOT_WITH_VEHICLE_CODE (LOT_CODE,PRODUCT_VEHICLE_CODE) VALUES "); MessageFormat messageFormat = new MessageFormat("(" + "#'{'list[{0}].lotCode }," + "#'{'list[{0}].productVehicleCode }" + ")"); int size = lotWithVehicleCodeBOs.size(); for (int i = 0; i < size; i++) { sb.append(messageFormat.format(new Object[]{i})); if (i < size - 1) sb.append(","); } return sb.toString(); }
3.service層
@Transactionalpublic void synchLotWithVehicleCodeToLocalDB(List<LotWithVehicleCodeBO> lotWithVehicleCodeBOs) { if(null != lotWithVehicleCodeBOs && lotWithVehicleCodeBOs.size()>0) { printMapper.insertAllLotWithVehicleCode(lotWithVehicleCodeBOs); } }
程序上線的時(shí)候沒有發(fā)生問題,在業(yè)務(wù)量猛增的時(shí)候,大約同時(shí)執(zhí)行500條以上的時(shí)候程序就開始報(bào)錯(cuò):
Caused by: org.apache.ibatis.builder.BuilderException: Improper inline parameter map format. Should be: #{propName,attr1=val1,attr2=val2} at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.buildParameterMapping(SqlSourceBuilder.java:89) at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.handleToken(SqlSourceBuilder.java:43) at org.apache.ibatis.parsing.GenericTokenParser.parse(GenericTokenParser.java:25) at org.apache.ibatis.builder.SqlSourceBuilder.parse(SqlSourceBuilder.java:24) at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:57) ... 61 more
異常已指明SQL語句構(gòu)建問題,DEBUG進(jìn)去:
問題根源:
MessageFormat messageFormat = new MessageFormat("(" + "#'{'list[{0}].lotCode }," + "#'{'list[{0}].productVehicleCode }," + ")"); int size = lotWithVehicleCodeBOs.size(); for (int i = 0; i < size; i++) { sb.append(messageFormat.format(new Object[]{i})); if (i<size-1) sb.append(","); }
當(dāng)size達(dá)到3位數(shù)以上時(shí)構(gòu)建出的message為:
(#{list[1,000].lotCode },#{list[1,000].productVehicleCode })
解決辦法:messageFormat.format(new Object[]{i+""}
相關(guān)文章
SQL Server 2016 CTP2.3 的關(guān)鍵特性總結(jié)
SQL Server2016 CTP2.2是微軟數(shù)據(jù)平臺(tái)歷史上邁出最大的一步,更快的事務(wù)處理和查詢、任何設(shè)備更深入的洞察力、更先進(jìn)的分析能力、全新安全技術(shù)和全新的混合云場(chǎng)景,本文給大家介紹SQL Server 2016 CTP2.3 的關(guān)鍵特性總結(jié),需要的朋友可以參考下2015-09-09一句Sql把縱向表轉(zhuǎn)為橫向表,并分別分組求平均和總平均值
一句Sql把縱向表轉(zhuǎn)為橫向表,并分別分組求平均和總平均值,需要的朋友可以參考下。2010-06-06使用linux?CentOS本地部署SQL?Server數(shù)據(jù)庫(kù)超詳細(xì)步驟
作為一名Linux愛好者,我們?cè)谑褂肔inux系統(tǒng)的時(shí)候,經(jīng)常需要使用到數(shù)據(jù)庫(kù),下面這篇文章主要給大家介紹了關(guān)于使用linux?CentOS本地部署SQL?Server數(shù)據(jù)庫(kù)的超詳細(xì)步驟,需要的朋友可以參考下2024-01-01sqlserver中向表中插入多行數(shù)據(jù)的insert語句
關(guān)于sql 2000中如何使用insert語句插入多行記錄,可是郁悶壞了我。2010-08-08SQL Server數(shù)據(jù)庫(kù)bcp導(dǎo)出備份文件應(yīng)用示例
本節(jié)主要介紹了SQL Server數(shù)據(jù)庫(kù)bcp導(dǎo)出備份文件應(yīng)用,需要的朋友可以參考下2014-08-08SQL SERVER2012中新增函數(shù)之字符串函數(shù)CONCAT詳解
SQL Server 2012有一個(gè)新函數(shù),就是CONCAT函數(shù),連接字符串非它莫屬。比如在它出現(xiàn)之前,連接字符串是使用"+"來連接,如遇上NULL,還得設(shè)置參數(shù)與配置,不然連接出來的結(jié)果將會(huì)是一個(gè)NULL。本文就介紹了關(guān)于SQL SERVER 2012中CONCAT函數(shù)的相關(guān)資料,需要的朋友可以參考。2017-03-03sql 游標(biāo)的使用—游標(biāo)FOR循環(huán)小例子
游標(biāo)for循環(huán)是在pl/sql塊中使用游標(biāo)最簡(jiǎn)單的方式,它簡(jiǎn)化了對(duì)游標(biāo)的處理。當(dāng)使用游標(biāo)for循環(huán)時(shí),oracle會(huì)隱含的打開游標(biāo),提取游標(biāo)數(shù)據(jù)并關(guān)閉游標(biāo)。2013-05-05