mybatis-3.4.6 foreach 自增主键
2020-07-24 本文已影响0人
晴天哥_王志
系列
- mybatis-3.4.6 配置介绍
- mybatis-3.4.6 顶层配置解析
- mybatis-3.4.6 子配置解析
- mybatis-3.4.6 mapper解析
- mybatis-3.4.6 SQL执行流程
- mybatis-3.4.6 SqlSession执行过程
- mybatis-3.4.6 缓存介绍
- mybatis-3.4.6 自增主键
- mybatis-3.4.6 foreach 自增主键
开篇
-
这个系列是基于mybatis-3.4.6版本的源码解析,这篇文章主要分析mybatis的foreach主键生成的逻辑。
-
这篇文章在mybatis-3.4.6 自增主键的基础上针对批量插入foreach的自增主键做个补充。
foreach
<insert id="bachAddUser" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="userId">
INSERT INTO imc_user (`user_nick`) VALUES
<foreach collection="list" item="item" index="index" separator=",">
(#{item.userNick})
</foreach>
</insert>
public class MybatisHelloWorld {
public static void main(String[] args) {
String resouce = "configuration.xml";
Reader reader;
try {
reader = Resources.getResourceAsReader(resouce);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
ImcUser imcUser = new ImcUser();
imcUser.setUserNick("demo");
ImcUser imcUser1 = new ImcUser();
imcUser1.setUserNick("demo1");
List<ImcUser> imcUserList = new ArrayList<>();
imcUserList.add(imcUser);
imcUserList.add(imcUser1);
userMapper.bachAddUser(imcUserList);
sqlSession.commit();
System.out.println(imcUserList.get(1).getUserId());
} finally {
sqlSession.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- foreach的批量插入的代码如上图所示。
ForEachHandler
private class ForEachHandler implements NodeHandler {
public ForEachHandler() {
// Prevent Synthetic Access
}
@Override
public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
String collection = nodeToHandle.getStringAttribute("collection");
String item = nodeToHandle.getStringAttribute("item");
String index = nodeToHandle.getStringAttribute("index");
String open = nodeToHandle.getStringAttribute("open");
String close = nodeToHandle.getStringAttribute("close");
String separator = nodeToHandle.getStringAttribute("separator");
ForEachSqlNode forEachSqlNode = new ForEachSqlNode(configuration, mixedSqlNode, collection, index, item, open, close, separator);
targetContents.add(forEachSqlNode);
}
}
- ForEachHandler的参数如上所示。
public class Jdbc3KeyGenerator implements KeyGenerator {
public static final Jdbc3KeyGenerator INSTANCE = new Jdbc3KeyGenerator();
@Override
public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
processBatch(ms, stmt, getParameters(parameter));
}
public void processBatch(MappedStatement ms, Statement stmt, Collection<Object> parameters) {
ResultSet rs = null;
try {
// 获取自增主键的ResultSet集合
rs = stmt.getGeneratedKeys();
final Configuration configuration = ms.getConfiguration();
final TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
final String[] keyProperties = ms.getKeyProperties();
final ResultSetMetaData rsmd = rs.getMetaData();
TypeHandler<?>[] typeHandlers = null;
if (keyProperties != null && rsmd.getColumnCount() >= keyProperties.length) {
// 批量的处理
for (Object parameter : parameters) {
// there should be one row for each statement (also one for each parameter)
if (!rs.next()) {
break;
}
final MetaObject metaParam = configuration.newMetaObject(parameter);
if (typeHandlers == null) {
typeHandlers = getTypeHandlers(typeHandlerRegistry, metaParam, keyProperties, rsmd);
}
populateKeys(rs, metaParam, keyProperties, typeHandlers);
}
}
} catch (Exception e) {
} finally {
}
}
private void populateKeys(ResultSet rs, MetaObject metaParam, String[] keyProperties, TypeHandler<?>[] typeHandlers) throws SQLException {
for (int i = 0; i < keyProperties.length; i++) {
String property = keyProperties[i];
TypeHandler<?> th = typeHandlers[i];
if (th != null) {
Object value = th.getResult(rs, i + 1);
metaParam.setValue(property, value);
}
}
}
}
- Jdbc3KeyGenerator处理批量插入的情况,和插入单个元素是一致的。