其他分享
首页 > 其他分享> > mybatis-KeyGenerator

mybatis-KeyGenerator

作者:互联网

1. 概述

本文,我们来分享 SQL 执行的第三部分,keygen 包。整体类图如下:类图

2. KeyGenerator

org.apache.ibatis.executor.keygen.KeyGenerator ,主键生成器接口。代码如下:

// KeyGenerator.java

public interface KeyGenerator {

// SQL 执行前
void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter);

// SQL 执行后
void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter);

}

KeyGenerator 有三个子类,如下图所示:类图

3. Jdbc3KeyGenerator

org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator ,实现 KeyGenerator 接口,基于 Statement#getGeneratedKeys() 方法的 KeyGenerator 实现类,适用于 MySQL、H2 主键生成。

3.1 构造方法

// Jdbc3KeyGenerator.java

/**
* A shared instance.
*
* 共享的单例
*
* @since 3.4.3
*/
public static final Jdbc3KeyGenerator INSTANCE = new Jdbc3KeyGenerator();

3.2 processBefore

@Override
public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
// do nothing
}

3.3 processAfter

// Jdbc3KeyGenerator.java

@Override
public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
processBatch(ms, stmt, parameter);
}

3.4 processBatch

// Jdbc3KeyGenerator.java

public void processBatch(MappedStatement ms, Statement stmt, Object parameter) {
// <1> 获得主键属性的配置。如果为空,则直接返回,说明不需要主键
final String[] keyProperties = ms.getKeyProperties();
if (keyProperties == null || keyProperties.length == 0) {
return;
}
ResultSet rs = null;
try {
// <2> 获得返回的自增主键
rs = stmt.getGeneratedKeys();
final Configuration configuration = ms.getConfiguration();
if (rs.getMetaData().getColumnCount() >= keyProperties.length) {
// <3> 获得唯一的参数对象
Object soleParam = getSoleParameter(parameter);
if (soleParam != null) {
// <3.1> 设置主键们,到参数 soleParam 中
assignKeysToParam(configuration, rs, keyProperties, soleParam);
} else {
// <3.2> 设置主键们,到参数 parameter 中
assignKeysToOneOfParams(configuration, rs, keyProperties, (Map<?, ?>) parameter);
}
}
} catch (Exception e) {
throw new ExecutorException("Error getting generated key or setting result to parameter object. Cause: " + e, e);
} finally {
// <4> 关闭 ResultSet 对象
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
// ignore
}
}
}
}

3.4.1 getSoleParameter

// Jdbc3KeyGenerator.java

/**
* 获得唯一的参数对象
*
* 如果获得不到唯一的参数对象,则返回 null
*
* @param parameter 参数对象
* @return 唯一的参数对象
*/
private Object getSoleParameter(Object parameter) {
// <1> 如果非 Map 对象,则直接返回 parameter
if (!(parameter instanceof ParamMap || parameter instanceof StrictMap)) {
return parameter;
}
// <3> 如果是 Map 对象,则获取第一个元素的值
// <2> 如果有多个元素,则说明获取不到唯一的参数对象,则返回 null
Object soleParam = null;
for (Object paramValue : ((Map<?, ?>) parameter).values()) {
if (soleParam == null) {
soleParam = paramValue;
} else if (soleParam != paramValue) {
soleParam = null;
break;
}
}
return soleParam;
}