今天主要学习是executor包下一个子包keygen,这个包功能就是自动生成一个key,例如@SelectKey注解设置字段,然后返回,生成key有两种,一种是通过jdbc生成,一种通过执行sql语句获取某个字段值实现生成key
/**
* 这个类的功能就是在执行完sql获取 stmt.getGeneratedKeys()生成keys的值,然后通过下标与配置keyProperty("id,name...")进行关联,通过
* typeHandler处理之后将值设置到对应keyProperties中,这里keyProperties是parameter中的字段,所以执行完之后,你可以执行从入参parameter
* 获取生成key的值,insert方法返回主键也就是利用这个方法。
* 1.使用jdbc生成key,它只处理执行sql之后
* 2.生成key,要与入参或出参匹配,然后设置值
* 3、从结果集中拿出对应属性的Typehandler,用Typehandler转换结果集的数据,将值设置到入参中,
* 4、这里keyProperties是MappedStatement.keyProperty("id,name")多个以逗号隔开
*
*
* @author Clinton Begin
* @author Kazuki Shimizu
*/
public class Jdbc3KeyGenerator implements KeyGenerator {
/**
* A shared instance.
* 恶汉模式直接创建一个实例
* @since 3.4.3
*/
public static final Jdbc3KeyGenerator INSTANCE = new Jdbc3KeyGenerator();
/**
* 生成多个key报错提示信息
*/
private static final String MSG_TOO_MANY_KEYS = "Too many keys are generated. There are only %d target objects. "
+ "You either specified a wrong 'keyProperty' or encountered a driver bug like #1523.";
@Override
public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
// do nothing
}
/**
* 处理完,从数据库中拿到key
* @param executor 执行器
* @param ms mapper解析成对象
* @param stmt SQL语句
* @param parameter 具体参数值
*/
@Override
public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
//因为是执行后获取生成key,所以不需要executor
processBatch(ms, stmt, parameter);
}
/**
* 批量处理key
* @param ms
* @param stmt
* @param parameter
*/
public void processBatch(MappedStatement ms, Statement stmt, Object parameter) {
//如果key属性对象数组为空,直接返回
final String[] keyProperties = ms.getKeyProperties();
if (keyProperties == null || keyProperties.length == 0) {
return;
}
//获取生成key结果集
// 获取其中一条数据
//获取Configuration对象
try (ResultSet rs = stmt.getGeneratedKeys()) {
final ResultSetMetaData rsmd = rs.getMetaData();
final Configuration configuration = ms.getConfiguration();
// 本身列数小于属性长度
if (rsmd.getColumnCount() < keyProperties.length) {
// Error?
} else {
//本身列数>=属性长度
assignKeys(configuration, rs, rsmd, keyProperties, parameter);
}
} catch (Exception e) {
throw new ExecutorException("Error getting generated key or setting result to parameter object. Cause: " + e, e);
}
}
/**
* 设置key的值
* @param configuration 配置对象
* @param rs 结果集(生成key)
* @param rsmd 结果集源数据
* @param keyProperties 属性对象
* @param parameter 参数
* @throws SQLException
*/
@SuppressWarnings("unchecked")
private void assignKeys(Configuration configuration, ResultSet rs, ResultSetMetaData rsmd, String[] keyProperties,
Object parameter) throws SQLException {
// 判断类型是不是ParamMap或StrictMap(本质是不是map)
if (parameter instanceof ParamMap || parameter instanceof StrictMap) {
// Multi-param or single param with @Param
assignKeysToParamMap(configuration, rs, rsmd, keyProperties, (Map<String, ?>) parameter);
} else if (parameter instanceof ArrayList && !((ArrayList<?>) parameter).isEmpty()
&& ((ArrayList<?>) parameter).get(0) instanceof ParamMap) {
// Multi-param or single param with @Param in batch operation
// 多个参数或单个参数用@Param进行批量操作
assignKeysToParamMapList(configuration, rs, rsmd, keyProperties, ((ArrayList<ParamMap<?>>) parameter));
} else {
// Single param without @Param
//单个参数没有使用 @Param
assignKeysToParam(configuration, rs, rsmd, keyProperties, parameter);
}
}
/**
* parameter的字段包含keyProperties, 根据keyProperty获取parameter对象中setter方法
* keyProperties是如何与 stmt.getGeneratedKeys() 关联起来,主要是通过下标进行约定,所以keyProperties下标+1, 变成ResultSet对应值的下标
* @param configuration 配置对象
* @param rs 结果集
* @param rsmd 结果集元数据
* @param keyProperties key 属性对象
* @param parameter 入参具体参数
* @throws SQLException
*/
private void assignKeysToParam(Configuration configuration, ResultSet rs, ResultSetMetaData rsmd,
String[] keyProperties, Object parameter) throws SQLException {
Collection<?> params = collectionize(parameter);
if (params.isEmpty()) {
return;
}
List<KeyAssigner> assignerList = new ArrayList<>();
for (int i = 0; i < keyProperties.length; i++) {
assignerList.add(new KeyAssigner(configuration, rsmd, i + 1, null, keyProperties[i]));
}
Iterator<?> iterator = params.iterator();
while (rs.next()) {
if (!iterator.hasNext()) {
throw new ExecutorException(String.format(MSG_TOO_MANY_KEYS, params.size()));
}
Object param = iterator.next();
assignerList.forEach(x -> x.assign(rs, param));
}
}
/**
* List
private void assignKeysToParamMapList(Configuration configuration, ResultSet rs, ResultSetMetaData rsmd,
String[] keyProperties, ArrayList<ParamMap<?>> paramMapList) throws SQLException {
//获取参数MapList迭代器
//创建一个KeyAssigner类
Iterator<ParamMap<?>> iterator = paramMapList.iterator();
List<KeyAssigner> assignerList = new ArrayList<>();
long counter = 0;
while (rs.next()) {
if (!iterator.hasNext()) {
throw new ExecutorException(String.format(MSG_TOO_MANY_KEYS, counter));
}
ParamMap<?> paramMap = iterator.next();
if (assignerList.isEmpty()) {
for (int i = 0; i < keyProperties.length; i++) {
assignerList
.add(getAssignerForParamMap(configuration, rsmd, i + 1, paramMap, keyProperties[i], keyProperties, false)
.getValue());
}
}
assignerList.forEach(x -> x.assign(rs, paramMap));
counter++;
}
}
/**
* 将key赋值给参数map
* @param configuration 配置对象
* @param rs 结果集
* @param rsmd 结果集元数据
* @param keyProperties key属性
* @param paramMap 参数map
* @throws SQLException
*/
private void assignKeysToParamMap(Configuration configuration, ResultSet rs, ResultSetMetaData rsmd,
String[] keyProperties, Map<String, ?> paramMap) throws SQLException {
//参数为空直接返回
if (paramMap.isEmpty()) {
return;
}
//key= value
//遍历keyProperties属性
// 参数封装成KeyAssigner集合
Map<String, Entry<Iterator<?>, List<KeyAssigner>>> assignerMap = new HashMap<>();
for (int i = 0; i < keyProperties.length; i++) {
Entry<String, KeyAssigner> entry = getAssignerForParamMap(configuration, rsmd, i + 1, paramMap, keyProperties[i],
keyProperties, true);
Entry<Iterator<?>, List<KeyAssigner>> iteratorPair = assignerMap.computeIfAbsent(entry.getKey(),
k -> entry(collectionize(paramMap.get(k)).iterator(), new ArrayList<>()));
iteratorPair.getValue().add(entry.getValue());
}
long counter = 0;
while (rs.next()) {
for (Entry<Iterator<?>, List<KeyAssigner>> pair : assignerMap.values()) {
if (!pair.getKey().hasNext()) {
throw new ExecutorException(String.format(MSG_TOO_MANY_KEYS, counter));
}
Object param = pair.getKey().next();
pair.getValue().forEach(x -> x.assign(rs, param));
}
counter++;
}
}
/**
* 获取赋值ParamMap
* @param config 配置对象
* @param rsmd 结果集元数据
* @param columnPosition 列位置
* @param paramMap 参数map
* @param keyProperty key 属性值
* @param keyProperties key属性
* @param omitParamName 是否忽略参数名称
* @return
*/
private Entry<String, KeyAssigner> getAssignerForParamMap(Configuration config, ResultSetMetaData rsmd,
int columnPosition, Map<String, ?> paramMap, String keyProperty, String[] keyProperties, boolean omitParamName) {
//单个参数
boolean singleParam = paramMap.values().stream().distinct().count() == 1;
//获取key属性的逗号的位置
//如果没有逗号,判断一下是不是单个参数
int firstDot = keyProperty.indexOf('.');
if (firstDot == -1) {
if (singleParam) {
return getAssignerForSingleParam(config, rsmd, columnPosition, paramMap, keyProperty, omitParamName);
}
throw new ExecutorException("Could not determine which parameter to assign generated keys to. "
+ "Note that when there are multiple parameters, 'keyProperty' must include the parameter name (e.g. 'param.id'). "
+ "Specified key properties are " + ArrayUtil.toString(keyProperties) + " and available parameters are "
+ paramMap.keySet());
}
// 设置paramName,从keyProperty中拿
String paramName = keyProperty.substring(0, firstDot);
if (paramMap.containsKey(paramName)) {
String argParamName = omitParamName ? null : paramName;
String argKeyProperty = keyProperty.substring(firstDot + 1);
return entry(paramName, new KeyAssigner(config, rsmd, columnPosition, argParamName, argKeyProperty));
} else if (singleParam) {
return getAssignerForSingleParam(config, rsmd, columnPosition, paramMap, keyProperty, omitParamName);
} else {
throw new ExecutorException("Could not find parameter '" + paramName + "'. "
+ "Note that when there are multiple parameters, 'keyProperty' must include the parameter name (e.g. 'param.id'). "
+ "Specified key properties are " + ArrayUtil.toString(keyProperties) + " and available parameters are "
+ paramMap.keySet());
}
}
/**
* 获取只有一个参数属性
* @param config 配置对象
* @param rsmd 结果集元数据
* @param columnPosition 列位置
* @param paramMap 参数map
* @param keyProperty key的属性
* @param omitParamName 是否忽略参数名称
* @return
*/
private Entry<String, KeyAssigner> getAssignerForSingleParam(Configuration config, ResultSetMetaData rsmd,
int columnPosition, Map<String, ?> paramMap, String keyProperty, boolean omitParamName) {
// Assume 'keyProperty' to be a property of the single param.
//获取paramMap的key
//是否忽略参数名称,如果忽略就是null,否则取paramMap中的key
String singleParamName = nameOfSingleParam(paramMap);
String argParamName = omitParamName ? null : singleParamName;
return entry(singleParamName, new KeyAssigner(config, rsmd, columnPosition, argParamName, keyProperty));
}
/**
* 从paramMap中拿出第一个key返回
* @param paramMap
* @return
*/
private static String nameOfSingleParam(Map<String, ?> paramMap) {
// There is virtually one parameter, so any key works.
return paramMap.keySet().iterator().next();
}
/**
* 具体化参数类型
* @param param
* @return
*/
private static Collection<?> collectionize(Object param) {
//集合
// Object[]
if (param instanceof Collection) {
return (Collection<?>) param;
} else if (param instanceof Object[]) {
return Arrays.asList((Object[]) param);
} else {
return Arrays.asList(param);
}
}
private static <K, V> Entry<K, V> entry(K key, V value) {
// Replace this with Map.entry(key, value) in Java 9.
// 创建简单不变的对象
return new AbstractMap.SimpleImmutableEntry<>(key, value);
}
/**
* 创建一个Key赋值对象
*/
private class KeyAssigner {
/**
* 配置对象
*/
private final Configuration configuration;
/**
* 结果集元数据
*/
private final ResultSetMetaData rsmd;
/**
* 类型处理注册(声明一下,什么类型需要什么类进行处理)
*/
private final TypeHandlerRegistry typeHandlerRegistry;
/**
* 列位置
*/
private final int columnPosition;
/**
* 参数名称
*/
private final String paramName;
/**
* 属性名称
*/
private final String propertyName;
/**
* 类型处理,把不同类结果用不同处理类进行处理,例如(Integer, 可以自己定义处理这种类型结果)
*/
private TypeHandler<?> typeHandler;
protected KeyAssigner(Configuration configuration, ResultSetMetaData rsmd, int columnPosition, String paramName,
String propertyName) {
super();
this.configuration = configuration;
this.rsmd = rsmd;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.columnPosition = columnPosition;
this.paramName = paramName;
this.propertyName = propertyName;
}
/**
* 赋值操作
* @param rs 结果集
* @param param 参数
*/
protected void assign(ResultSet rs, Object param) {
//如果参数名称不为空,替换param
if (paramName != null) {
// If paramName is set, param is ParamMap
param = ((ParamMap<?>) param).get(paramName);
}
//将param分解元对象
MetaObject metaParam = configuration.newMetaObject(param);
try {
//如果类型处理为null
//如果有这个属性名的setter的方法
//主要是获取typeHandler对象
if (typeHandler == null) {
if (metaParam.hasSetter(propertyName)) {
Class<?> propertyType = metaParam.getSetterType(propertyName);
typeHandler = typeHandlerRegistry.getTypeHandler(propertyType,
JdbcType.forCode(rsmd.getColumnType(columnPosition)));
} else {
throw new ExecutorException("No setter found for the keyProperty '" + propertyName + "' in '"
+ metaParam.getOriginalObject().getClass().getName() + "'.");
}
}
if (typeHandler == null) {
// Error?
} else {
//获取结果的值
Object value = typeHandler.getResult(rs, columnPosition);
metaParam.setValue(propertyName, value);
}
} catch (SQLException e) {
throw new ExecutorException("Error getting generated key or setting result to parameter object. Cause: " + e,
e);
}
}
}
}
/**
* 通过select的sql语句获取key
* @author Clinton Begin
* @author Jeff Butler
*/
public class SelectKeyGenerator implements KeyGenerator {
/**
* selectkey前缀
*/
public static final String SELECT_KEY_SUFFIX = "!selectKey";
/**
* 是否在执行sql之前
*/
private final boolean executeBefore;
/**
* 获取key的sql语句
*/
private final MappedStatement keyStatement;
public SelectKeyGenerator(MappedStatement keyStatement, boolean executeBefore) {
this.executeBefore = executeBefore;
this.keyStatement = keyStatement;
}
@Override
public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
if (executeBefore) {
processGeneratedKeys(executor, ms, parameter);
}
}
@Override
public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
if (!executeBefore) {
processGeneratedKeys(executor, ms, parameter);
}
}
/**
* 通过执行sql获取keys
* @param executor 执行器
* @param ms mapper语句
* @param parameter 参数对象
*/
private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) {
try {
//入参不为空,查询key的sql不能为空,当然字段key也不能为空
//获取key属性
//获取configuration配置对象
//将参数对象解析成元对象
if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) {
String[] keyProperties = keyStatement.getKeyProperties();
final Configuration configuration = ms.getConfiguration();
final MetaObject metaParam = configuration.newMetaObject(parameter);
if (keyProperties != null) {
// Do not close keyExecutor.
// The transaction will be closed by parent executor.
// 创建一个Executor对象
Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE);
List<Object> values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
if (values.size() == 0) {
throw new ExecutorException("SelectKey returned no data.");
} else if (values.size() > 1) {
throw new ExecutorException("SelectKey returned more than one value.");
} else {
MetaObject metaResult = configuration.newMetaObject(values.get(0));
//属性
if (keyProperties.length == 1) {
// 获取第一个值
if (metaResult.hasGetter(keyProperties[0])) {
//设置返回values.get(0)对象的某个字段的值
setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0]));
} else {
// no getter for the property - maybe just a single value object
// so try that
//只有本身就是有一个值
setValue(metaParam, keyProperties[0], values.get(0));
}
} else {
handleMultipleProperties(keyProperties, metaParam, metaResult);
}
}
}
}
} catch (ExecutorException e) {
throw e;
} catch (Exception e) {
throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e);
}
}
/**
* 处理多个properties key
* @param keyProperties keyProperties
* @param metaParam 返回参数元对象
* @param metaResult 从数据库查询结果元对象
*/
private void handleMultipleProperties(String[] keyProperties,
MetaObject metaParam, MetaObject metaResult) {
String[] keyColumns = keyStatement.getKeyColumns();
//如果没有设置keyColumns不需要校验 keyColumns的长度必须等于keyProperties的长度
if (keyColumns == null || keyColumns.length == 0) {
// no key columns specified, just use the property names
for (String keyProperty : keyProperties) {
setValue(metaParam, keyProperty, metaResult.getValue(keyProperty));
}
} else {
if (keyColumns.length != keyProperties.length) {
throw new ExecutorException("If SelectKey has key columns, the number must match the number of key properties.");
}
for (int i = 0; i < keyProperties.length; i++) {
setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i]));
}
}
}
/**
* 设置值
* @param metaParam 返回给parameter
* @param property 字段名
* @param value 值
*/
private void setValue(MetaObject metaParam, String property, Object value) {
if (metaParam.hasSetter(property)) {
metaParam.setValue(property, value);
} else {
throw new ExecutorException("No setter found for the keyProperty '" + property + "' in " + metaParam.getOriginalObject().getClass().getName() + ".");
}
}
}