zoukankan      html  css  js  c++  java
  • Mybatis拦截器 mysql load data local 内存流处理

    Mybatis 拦截器不做解释了,用过的基本都知道,这里用load data local主要是应对大批量数据的处理,提高性能,也支持事务回滚,且不影响其他的DML操作,当然这个操作不要涉及到当前所load的数据,其中在使用的时候一定要local , 这个命令使用是mysql规定的,否则不加则会认为是服务器本地的文件。这里主要是以流的方式来做处理,这样可以使用内存流,这样就可以避免在某些时候需要生成文件才能导入的多余操作,和IO性能消耗。也可以是应用本地的文件。

    注:该做法只试用于存入数据的表,不试用于有频繁更新,查询操作的表。 因为load 命令的优先级比更新命令,及查询命令的优先级低。

    mybatis 插件配置

    <plugins>
       <plugin interceptor="com.yunat.channel.process.util.LoadDataInterceptor">
           <property name="databaseType" value="mysql"/>
       </plugin>
    </plugins>

    插入SQL

    <select id="saveTest" parameterType="map">
        LOAD DATA LOCAL INFILE 'sql.csv' IGNORE INTO TABLE test (a,b,d)
    </select>

    插件代码

    package com.yunat.channel.process.util;
     
    import java.io.InputStream;
    import java.sql.Statement;
    import java.util.Properties;
     
    import org.apache.ibatis.executor.statement.RoutingStatementHandler;
    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.plugin.Interceptor;
    import org.apache.ibatis.plugin.Intercepts;
    import org.apache.ibatis.plugin.Invocation;
    import org.apache.ibatis.plugin.Plugin;
    import org.apache.ibatis.plugin.Signature;
     
    @Intercepts({ @Signature(method = "update", type = StatementHandler.class, args = { Statement.class }) })
    public class LoadDataInterceptor implements Interceptor {
     
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();
            BoundSql boundSql = handler.getBoundSql();
            if (boundSql.getSql().toLowerCase().contains("load data local infile")) {
                Object in = boundSql.getParameterObject();
                if (in != null && in instanceof InputStream) { // 如果不使用流的方式, 则会读取语句中对应在本地的文件
                    Statement statement = (Statement) invocation.getArgs()[0];
                    if (statement.isWrapperFor(com.mysql.jdbc.Statement.class)) {
                        com.mysql.jdbc.PreparedStatement mysqlStatement = statement.unwrap(com.mysql.jdbc.PreparedStatement.class);
                        // 将流设置到执行语句中,在后续执行过程中,会忽略load data 语句中的文件名,改用当前设置流
                        mysqlStatement.setLocalInfileInputStream((InputStream)in);
                        invocation.getArgs()[0] = mysqlStatement; // 将当前语句执行代理,换成mysql的语句对象,方便下面执行。
                    }
                }
            }
            return invocation.proceed();
        }
     
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
     
        @Override
        public void setProperties(Properties properties) {
     
        }
     
    }

    本文转自:http://www.oschina.net/code/snippet_144320_24440#66175

  • 相关阅读:
    RESTful规范
    浏览器缓存(强缓存和协商缓存)
    react hooks useState更新数据不及时问题及处理
    css提升页面渲染新属性content-visibility
    Mongodb Sort Operations
    mongodb使用小点
    Visual Studio 2017 中的Git源代码控制中使用BeyondCompare 3
    “指纹登录“ -- 项目中用到的两个cordova插件基本使用
    代码段:通过索引获取对应的Excel列名; 索引从0开始,返回形如 A,B,C,...,Z,AA,AB,...,AZ,BA,...,ZZ,AAA,AAB,......
    初学knockoutjs记录9——Bindings 绑定(1 Controling text and appearance 控制文本和外观)
  • 原文地址:https://www.cnblogs.com/dreammyle/p/5533504.html
Copyright © 2011-2022 走看看