一. insert 首先看一下 insert.java 的代碼: /** * <p> * 根據 ID 刪除 * </p> * * @author hubin * @since 2018-04-06 */ public class Insert extends AbstractMethod { @Ov ...
一. insert
首先看一下 insert.java 的代碼:
/** * <p> * 根據 ID 刪除 * </p> * * @author hubin * @since 2018-04-06 */ public class Insert extends AbstractMethod { @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { KeyGenerator keyGenerator = new NoKeyGenerator(); SqlMethod sqlMethod = SqlMethod.INSERT_ONE; String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumn(), StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET, null, StringPool.COMMA); String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlProperty(), StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET, null, StringPool.COMMA); String keyProperty = null; String keyColumn = null; // 表包含主鍵處理邏輯,如果不包含主鍵當普通欄位處理 if (StringUtils.isNotEmpty(tableInfo.getKeyProperty())) { if (tableInfo.getIdType() == IdType.AUTO) { /** 自增主鍵 */ keyGenerator = new Jdbc3KeyGenerator(); keyProperty = tableInfo.getKeyProperty(); keyColumn = tableInfo.getKeyColumn(); } else { if (null != tableInfo.getKeySequence()) { keyGenerator = TableInfoHelper.genKeyGenerator(tableInfo, builderAssistant, sqlMethod.getMethod(), languageDriver); keyProperty = tableInfo.getKeyProperty(); keyColumn = tableInfo.getKeyColumn(); } } } String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); return this.addInsertMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource, keyGenerator, keyProperty, keyColumn); } }
可以看到 insert 繼承了 AbstractMethod 類.
1. ableInfo.getAllInsertSqlColumn()
/** * 獲取 inset 時候欄位 sql 腳本片段 * insert into table (欄位) values (值) * 位於 "欄位" 部位 * * @return sql 腳本片段 */ public String getAllInsertSqlColumn() { return getKeyInsertSqlColumn() + fieldList.stream().map(TableFieldInfo::getInsertSqlColumn) .collect(joining(StringPool.NEWLINE)); }
getInsertSqlColumn() 方法, 拿列名:
/** * 獲取 inset 時候欄位 sql 腳本片段 * insert into table (欄位) values (值) * 位於 "欄位" 部位 * * @return sql 腳本片段 */ public String getInsertSqlColumn() { String sqlScript = column + StringPool.COMMA; if (fieldFill == FieldFill.INSERT || fieldFill == FieldFill.INSERT_UPDATE) { return sqlScript; } return convertIf(sqlScript, property); }
getKeyInsertSqlColumn()就是根據配置看是否要拿 id , 進入sql列的拼裝:
/** * 獲取 inset 時候主鍵 sql 腳本片段 * insert into table (欄位) values (值) * 位於 "欄位" 部位 * * @return sql 腳本片段 */ public String getKeyInsertSqlColumn() { if (StringUtils.isNotEmpty(keyColumn)) { if (idType == IdType.AUTO) { return StringPool.EMPTY; } return keyColumn + StringPool.COMMA + StringPool.NEWLINE; } return StringPool.EMPTY; }
如果 id 配置了 自動生成, 則在生成 sql 的列的時候, id不參與. 也就是說, 生成的語句是 insert name, age values(#{name}, #{age})
2. SqlScriptUtils.convertTrim()
/** * <p> * 獲取 帶 trim 標簽的腳本 * </p> * * @param sqlScript sql 腳本片段 * @param prefix 以...開頭 * @param suffix 以...結尾 * @param prefixOverrides 幹掉最前一個... * @param suffixOverrides 幹掉最後一個... * @return trim 腳本 */ public static String convertTrim(final String sqlScript, final String prefix, final String suffix, final String prefixOverrides, final String suffixOverrides) { StringBuilder sb = new StringBuilder("<trim"); if (StringUtils.isNotEmpty(prefix)) { sb.append(" prefix=\"").append(prefix).append(StringPool.QUOTE); } if (StringUtils.isNotEmpty(suffix)) { sb.append(" suffix=\"").append(suffix).append(StringPool.QUOTE); } if (StringUtils.isNotEmpty(prefixOverrides)) { sb.append(" prefixOverrides=\"").append(prefixOverrides).append(StringPool.QUOTE); } if (StringUtils.isNotEmpty(suffixOverrides)) { sb.append(" suffixOverrides=\"").append(suffixOverrides).append(StringPool.QUOTE); } return sb.append(StringPool.RIGHT_CHEV).append(StringPool.NEWLINE).append(sqlScript) .append(StringPool.NEWLINE).append("</trim>").toString(); }
實例中, 執行完後, columnScript 的結果是:
<trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null">name,</if> <if test="age != null">age,</if> <if test="email != null">email,</if> <if test="sex != null">sex,</if> </trim>
3. tableInfo.getAllInsertSqlProperty()
/** * 獲取所有 inset 時候插入值 sql 腳本片段 * insert into table (欄位) values (值) * 位於 "值" 部位 * * @return sql 腳本片段 */ public String getAllInsertSqlProperty() { return getKeyInsertSqlProperty() + fieldList.stream().map(TableFieldInfo::getInsertSqlProperty) .collect(joining(StringPool.NEWLINE)); } /** * 獲取 inset 時候插入值 sql 腳本片段 * insert into table (欄位) values (值) * 位於 "值" 部位 * * @return sql 腳本片段 */ public String getInsertSqlProperty() { String sqlScript = SqlScriptUtils.safeParam(el) + StringPool.COMMA; if (fieldFill == FieldFill.INSERT || fieldFill == FieldFill.INSERT_UPDATE) { return sqlScript; } return convertIf(sqlScript, property); } /** * <p> * 安全入參: #{入參} * </p> * * @param param 入參 * @return 腳本 */ public static String safeParam(final String param) { return StringPool.HASH_LEFT_BRACE + param + StringPool.RIGHT_BRACE; }
執行完之後, valuesScript 的值為:
<if test="name != null">#{name},</if> <if test="age != null">#{age},</if> <if test="email != null">#{email},</if> <if test="sex != null">#{sex},</if>
拼裝起來的 sql :
<script> INSERT INTO user <trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null">name,</if> <if test="age != null">age,</if> <if test="email != null">email,</if> <if test="sex != null">sex,</if> </trim> VALUES <trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null">#{name},</if> <if test="age != null">#{age},</if> <if test="email != null">#{email},</if> <if test="sex != null">#{sex},</if> </trim> </script>
拿到這個sql之後, 就可以創建 SqlSource 了. 然後放到 MappedStatement 裡面去.