All Downloads are FREE. Search and download functionalities are using the official Maven repository.

app.myoss.cloud.mybatis.mapper.template.insert.impl.InsertMapperTemplate Maven / Gradle / Ivy

/*
 * Copyright 2018-2018 https://github.com/myoss
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package app.myoss.cloud.mybatis.mapper.template.insert.impl;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.builder.xml.XMLStatementBuilder;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.mapping.StatementType;
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.parsing.XPathParser;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.session.Configuration;

import app.myoss.cloud.mybatis.executor.keygen.SequenceKeyGenerator;
import app.myoss.cloud.mybatis.mapper.template.AbstractMapperTemplate;
import app.myoss.cloud.mybatis.mapper.template.insert.InsertAllColumnMapper;
import app.myoss.cloud.mybatis.mapper.template.insert.InsertBatchMapper;
import app.myoss.cloud.mybatis.mapper.template.insert.InsertMapper;
import app.myoss.cloud.mybatis.table.TableColumnInfo;
import app.myoss.cloud.mybatis.table.TableInfo;
import app.myoss.cloud.mybatis.table.TableMetaObject;
import app.myoss.cloud.mybatis.table.TableSequence;
import app.myoss.cloud.mybatis.table.annotation.FillRule;
import app.myoss.cloud.mybatis.table.annotation.GenerationType;
import app.myoss.cloud.mybatis.table.annotation.SequenceGenerator.Order;

/**
 * 生成通用 insert MappedStatement 模版类
 *
 * @author Jerry.Chen
 * @since 2018年4月29日 下午4:46:05
 */
public class InsertMapperTemplate extends AbstractMapperTemplate {
    /**
     * 生成 selectKey 序列,并增加到 {@link Configuration} 全局配置中
     *
     * @param id mappedStatement id
     * @param sequence 数据库表"序列生成器"属性配置
     * @param parameterTypeClass "实体类"的 class
     * @param configuration Mybatis Global Configuration
     * @param langDriver Mybatis langDriver
     * @param parentId mappedStatement parent id
     * @return 生成 selectKey 序列对象
     * @see GenerationType#SELECT_KEY
     * @see XMLStatementBuilder#parseSelectKeyNodes
     */
    private SelectKeyGenerator addSelectKeyGenerator(String id, TableSequence sequence, Class parameterTypeClass,
                                                     Configuration configuration, LanguageDriver langDriver,
                                                     String parentId) {
        Class resultTypeClass = sequence.getResultType()[0];
        StatementType statementType = sequence.getStatementType();
        String keyProperty = StringUtils.join(sequence.getKeyProperties(), ",");
        String keyColumn = StringUtils.join(sequence.getKeyColumns(), ",");
        boolean executeBefore = sequence.getOrder().equals(Order.BEFORE);

        // 生成 selectKey sql
        String selectSql = sequence.getSql();
        StringBuilder sqlXml = new StringBuilder(150 + selectSql.length());
        sqlXml.append("").append(selectSql).append("");
        XPathParser xPathParser = new XPathParser(sqlXml.toString());
        XNode nodeToHandle = xPathParser.evalNode("selectKey");

        SqlSource sqlSource = langDriver.createSqlSource(configuration, nodeToHandle, parameterTypeClass);
        SqlCommandType sqlCommandType = SqlCommandType.SELECT;
        KeyGenerator keyGenerator = new NoKeyGenerator();
        MapperBuilderAssistant builderAssistant = new MapperBuilderAssistant(configuration, parentId);
        builderAssistant.setCurrentNamespace(StringUtils.substringBeforeLast(parentId, "."));
        builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, null, null, null,
                parameterTypeClass, null, resultTypeClass, null, false, false, false, keyGenerator, keyProperty,
                keyColumn, null, langDriver, null);

        id = builderAssistant.applyCurrentNamespace(id, false);

        MappedStatement keyStatement = configuration.getMappedStatement(id, false);
        SelectKeyGenerator selectKeyGenerator = new SelectKeyGenerator(keyStatement, executeBefore);
        configuration.addKeyGenerator(id, selectKeyGenerator);
        return selectKeyGenerator;
    }

    /**
     * 生成"序列生成器"
     *
     * @param tableInfo 数据库表结构信息
     * @param metaObject Mybatis * @param metaObject Mybatis
     * @param id mappedStatement id
     * @param configuration Mybatis Global Configuration
     * @return 序列生成策略
     */
    private GenerationType addKeyGenerator(TableInfo tableInfo, MetaObject metaObject, String id,
                                           Configuration configuration) {
        TableSequence tableSequence = tableInfo.getTableSequence();
        if (tableSequence == null) {
            return null;
        }
        GenerationType strategy = tableSequence.getStrategy();
        KeyGenerator keyGenerator;
        if (strategy == GenerationType.USE_GENERATED_KEYS) {
            keyGenerator = new Jdbc3KeyGenerator();
        } else if (strategy == GenerationType.SELECT_KEY) {
            String selectId = StringUtils.substringAfterLast(id, ".") + SelectKeyGenerator.SELECT_KEY_SUFFIX;
            keyGenerator = addSelectKeyGenerator(selectId, tableSequence, tableInfo.getEntityClass(), configuration,
                    xmlLanguageDriver, id);
        } else if (strategy == GenerationType.SEQUENCE_KEY) {
            boolean executeBefore = tableSequence.getOrder().equals(Order.BEFORE);
            keyGenerator = new SequenceKeyGenerator(tableInfo, id, executeBefore);
        } else {
            throw new UnsupportedOperationException("keyGenerator strategy " + strategy.getType() + " unsupported");
        }
        metaObject.setValue("keyGenerator", keyGenerator);
        return strategy;
    }

    /**
     * 创建新的记录,生成 insert 语句。
     * 

* 示例如下: * *

     * INSERT INTO table_name (id, ...) VALUES (#{id}, ...)
     * 
* * @param tableInfo 数据库表结构信息 * @param ms sql语句节点信息,会将生成的sql语句替换掉原有的 {@link MappedStatement#sqlSource} * @return 生成的sql语句 * @see InsertAllColumnMapper#insertAllColumn(Object) */ public String insertAllColumn(TableInfo tableInfo, MappedStatement ms) { MetaObject metaObject = SystemMetaObject.forObject(ms); String id = ms.getId(); Configuration configuration = ms.getConfiguration(); // 生成"序列生成器" addKeyGenerator(tableInfo, metaObject, id, configuration); // 生成 sql 语句 StringBuilder builder = new StringBuilder(2048); builder.append("INSERT INTO ").append(TableMetaObject.getTableName(tableInfo)).append(" ("); StringBuilder values = new StringBuilder(1024); for (TableColumnInfo columnInfo : tableInfo.getColumns()) { if (!columnInfo.isInsertable() || columnInfo.isAutoIncrement()) { continue; } builder.append(columnInfo.getActualColumn()).append(", "); values.append("#{").append(columnInfo.getProperty()); if (columnInfo.getJdbcType() != null) { values.append(",jdbcType=BIGINT"); } values.append("}, "); } values.deleteCharAt(values.length() - 2); builder.deleteCharAt(builder.length() - 2).append(")\n"); builder.append(" VALUES (").append(values).append(")"); String sql = builder.toString(); // 替换 sqlSource 对象 SqlSource sqlSource = xmlLanguageDriver.createSqlSource(configuration, "", null); metaObject.setValue("sqlSource", sqlSource); return sql; } /** * 创建新的记录,生成 insert 语句。 *

* 示例如下: * *

     * INSERT INTO table_name
     * <trim prefix="(" suffix=")" suffixOverrides=",">
     *   <if test="id != null">
     *     id,
     *   </if>
     * </trim>
     * <trim prefix="values (" suffix=")" suffixOverrides=",">
     *   <if test="id != null">
     *     #{id},
     *   </if>
     * </trim>
     * 
* * @param tableInfo 数据库表结构信息 * @param ms sql语句节点信息,会将生成的sql语句替换掉原有的 {@link MappedStatement#sqlSource} * @return 生成的sql语句 * @see InsertMapper#insert(Object) */ public String insert(TableInfo tableInfo, MappedStatement ms) { MetaObject metaObject = SystemMetaObject.forObject(ms); String id = ms.getId(); Configuration configuration = ms.getConfiguration(); // 生成"序列生成器" GenerationType generationType = addKeyGenerator(tableInfo, metaObject, id, configuration); // 生成 sql 语句 StringBuilder builder = new StringBuilder(4096); builder.append("INSERT INTO ").append(TableMetaObject.getTableName(tableInfo)).append("\n"); builder.append("\n"); StringBuilder values = new StringBuilder(2048); values.append("\n"); for (TableColumnInfo columnInfo : tableInfo.getColumns()) { if (!columnInfo.isInsertable() || columnInfo.isAutoIncrement()) { continue; } // 如果是主键字段(不是自动增长的主键)或者字段有自动填充的规则,不加 if 表达式判断 boolean fillInsert = (columnInfo.isPrimaryKey() && GenerationType.USE_GENERATED_KEYS != generationType) || columnInfo.haveFillRule(FillRule.INSERT); if (!fillInsert) { builder.append(" \n"); } builder.append(" ").append(columnInfo.getActualColumn()).append(",\n"); if (!fillInsert) { builder.append(" \n"); } if (!fillInsert) { values.append(" \n"); } values.append(" #{").append(columnInfo.getProperty()); if (columnInfo.getJdbcType() != null) { values.append(",jdbcType=BIGINT"); } values.append("},\n"); if (!fillInsert) { values.append(" \n"); } } builder.append("\n").append(values).append("\n"); String sql = builder.toString(); // 替换 sqlSource 对象 SqlSource sqlSource = xmlLanguageDriver.createSqlSource(configuration, "", null); metaObject.setValue("sqlSource", sqlSource); return sql; } /** * 批量创建新的记录,生成 insert 语句。 *

* 示例如下: * *

     * INSERT INTO table_name (id, ...) VALUES
     * <foreach collection="list" item="item" separator=",">
     * (#{id}, ...)
     * </foreach>
     * 
* * @param tableInfo 数据库表结构信息 * @param ms sql语句节点信息,会将生成的sql语句替换掉原有的 {@link MappedStatement#sqlSource} * @return 生成的sql语句 * @see InsertBatchMapper#insertBatch(List) */ public String insertBatch(TableInfo tableInfo, MappedStatement ms) { MetaObject metaObject = SystemMetaObject.forObject(ms); String id = ms.getId(); Configuration configuration = ms.getConfiguration(); // 生成"序列生成器" addKeyGenerator(tableInfo, metaObject, id, configuration); // 生成 sql 语句 StringBuilder builder = new StringBuilder(2048); builder.append("INSERT INTO ").append(TableMetaObject.getTableName(tableInfo)).append(" ("); StringBuilder values = new StringBuilder(1024); values.append(""); values.append("\n("); for (TableColumnInfo columnInfo : tableInfo.getColumns()) { if (!columnInfo.isInsertable() || columnInfo.isAutoIncrement()) { continue; } builder.append(columnInfo.getActualColumn()).append(", "); values.append("#{item.").append(columnInfo.getProperty()); if (columnInfo.getJdbcType() != null) { values.append(",jdbcType=BIGINT"); } values.append("}, "); } values.deleteCharAt(values.length() - 2).append(")\n"); builder.deleteCharAt(builder.length() - 2).append(")\n"); builder.append(" values \n").append(values); String sql = builder.toString(); // 替换 sqlSource 对象 SqlSource sqlSource = xmlLanguageDriver.createSqlSource(configuration, "", null); metaObject.setValue("sqlSource", sqlSource); return sql; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy