##第一种:错误写法 <!-- ##第二种:正确写法 <insert id="batchInsert" parameterType="xxx"> <!--注意这里参数类型写成java.util.List和具体对象类型,都可以正常插入数据--> |
你可能也会像我一样,既然单个数据的插入有一个insertSelective,为什么在批量插入的时候不可以有呢?于是你可能就会试着写一段代码,比如上图中的第一种,乍一看,好像也没有什么问题,但是当你运行代码的过程中,就会报一个错误,那就是:
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'ERID' not found. Available parameters are [collection, list]
提示无法找到对应的参数ERID,其实不是只是这一个找不到,后面的参数都找不到的。
于是我们就想,这个ERID是封装实体类中的一个属性,按照第二种方式可以正常插入数据,那么就能说明,批量插入的值的传递,其写法是正确。也就foreach中,定义的是一个集合,它的item就是集合中的对象,对象的属性值就是我们想要插入的字段值。因此只能是insert后面values之前的对象属性无法找到对应的属性才会报错,为了验证我们的思想,我们可以把那些判断条件去掉。再试一次。于是就变成了下面这样。
<insert id="batchInsert" parameterType="xxx"> |
在运行的过程中,我们可以发现,没有报相关的属性找不到了(因为我们传递的是list,insert后面它没有直接去对象中找相关的属性了,也就是没有list.ERID了,而是直接写死的,就是指定插入这些字段的值),说明我们刚才的推想是正确的。但是这样就面临一个问题,那就是属性上没有加入判断,而插入的值对其相应的属性做了判断,这就导致,所有的插入的字段与传递的值的数量可能会出现不一致的情况。当然对象也都可以设置默认值作为解决,但这样下面的判断不就显得多余了吗?
这里的报错内容是:
org.springframework.jdbc.UncategorizedSQLException:
### Error updating database. Cause: java.sql.SQLException: [e1dc03feac00000-2][172.169.101.107:3306][mysql1]ERR-CODE: [TDDL-4501][ERR_OPTIMIZER] optimize error by Column count doesn't match value count More:
因此走到这里,我们写出正确的代码就是第二种,但是这偏离了我们的意愿,我是想对批量插入的字段进行判断的,难道真的就不可以了吗!!!事实上就是不可以
且看:我们定义的接口中的方法:
int batchInsert(List<MonitorErInfo> list);
再次想一下:集合中具体的对象这里为MonitorErInfo,它的属性值是ERID,workStatus等这些,我们想加入的判断条件是因为这些属性的值是否存在存在不确定性。这体现到sql中就明显了,对于单个数据的插入,在insert和values后面对相关的属性进行判断,这样的话,无论如何insert后面的字段数量和values后面的需要插入的值,都是一一对应的,不多也不少。
但是针对批量插入,这就不行了。实际上批量插入执行的sql是这样的
insert into tableA(x,y,z) values (a,b,c),(d,e,f),(h,j,k), (...)
sql不支持这样的语句,比如
insert into tableA(x,y,z) values(a),(b,c),(d,e,f)
道理很简单,比如a,你怎么知道这个值是插入到x,y还是z呢!
你有可能想到占位,比如可以这样写
insert into tableA(x,y,z) values(a,null,null),(null,b,c),(d,e,f)
但是这样不就是回到第二种方法了吗!我们判断的条件依旧没有加上啊!
既然values后面无法使用,那么在insert后面values之前做做手脚呢?
其实也是行不通的,insert后面如果不指定数据库字段的名称,那么values后面即使指定了它的值也是插入不进去的,即便插入进去了,也不是那个字段对应的值了,不对应了,因此,如果values后面的属性值不确定,那么如果全部的属性都有值的话,意味着,insert后values之前的数据库字段都应该存在。再结合之前的分析,如果这些字段都有存在,要保证插入的数据值和字段一一对应,那么values必须每个位上都有值,这就意味着,我们无法通过属性判断,来决定哪些值需要插入,哪些值不需要插入。属性值的判断也就失去了意义!