mybatis-3.2.7执行批量插入语句并返回主键时代码报错,经过确认是代码的bug,升级版本到3.3.1后正常。
下面通过源码分析一下批量插入时返回主键的原理,以及造成这个bug的原因。
错误信息如下:
1 |
|
下面从头梳理一下这个问题,一般处理批量插入的写法是:
1 |
|
1 |
|
mybatis批量插入并返回主键的理论依赖
JDBC的java.sql.Statement
接口提供了方法
ResultSet getGeneratedKeys() throws SQLException;
这个方法返回可以返回主键
只要在SQL语句执行完成后往实体类填充主键即可实现返回主键的目的
具体代码实现
先简单说一下mybatis的代码结构
- SqlSession负责处理最外层的增删改查逻辑,可以直接返回查询的实体类
- Executor及其实现类SimpleExecutor, ReuseExecutor, BatchExecutor等进一步包装SqlSession传过来的SQL语句,并且负责处理对象关系映射,这个mybatis作为一个ORM(Object Relation Mapping)的核心
- 进一步Executor将处理逻辑递交给StatementHandler,这一层主要负责执行JDBC提供的java.sql.Statement或者java.sql.PreparedStatement语句,并从java.sql.ResultSet中得到SQL执行的结果
完成填充主键这一步就是在StatementHandler这一层,具体是在org.apache.ibatis.executor.statement.PreparedStatementHandler#update
,代码如下:
1 |
|
org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator#processAfter
的主要代码如下
1 |
|
mybatis-3.2.7与mybatis-3.3.1的代码不同之处就在于
processBatch(ms, stmt, getParameters(parameter));
中对入参多了一步处理,调用了getParameters
方法,代码如下
该方法将参数从Map中抽取出来,之所以这么做是因为一开始mybatis将参数对象放在了map中进行了处理,所以这里要从Map中再提取出来。
而mybatis-3.2.7的代码没有这一步,导致了后面去设置主键ID的时候,找不到这个属性,因此直接报错。
1 |
|