欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MyBatis MapperProvider MessageFormat拼接批量SQL语句执行报错的原因分析及解决办法

程序员文章站 2022-04-14 11:34:32
最近在项目中有这么一段代码:下载服务器基础业务数据进行本地批量插入操作,因项目中使用mybatis进行持久化操作,故直接考虑使用mybatis的批量插入功能。 1.以下是...

最近在项目中有这么一段代码:下载服务器基础业务数据进行本地批量插入操作,因项目中使用mybatis进行持久化操作,故直接考虑使用mybatis的批量插入功能。

1.以下是mapper接口的部分代码

public interface printmapper
{
@insertprovider(type = printmapperprovider.class,method = "insertalllotwithvehiclecode4h2") void insertalllotwithvehiclecode(list<lotwithvehiclecodebo> lotwithvehiclecodes);
}

2.对应mapperprovider中函数片段

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);
}
}

程序上线的时候没有发生问题,在业务量猛增的时候,大约同时执行500条以上的时候程序就开始报错:

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语句构建问题,debug进去:

问题根源:

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(",");
}

当size达到3位数以上时构建出的message为:

(#{list[1,000].lotcode },#{list[1,000].productvehiclecode })

解决办法:messageformat.format(new object[]{i+""}