前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mybatis/Mybatis-plus执行动态sql片段工具类

Mybatis/Mybatis-plus执行动态sql片段工具类

作者头像
4xx.me
发布2022-09-23 12:50:42
1K0
发布2022-09-23 12:50:42
举报

在开发中可能会遇到需要执行动态sql的场景,比如前端传输sql片段或参数,后端拼接sql语句来执行

参考文章:https://www.codeleading.com/article/90405694877/

先看效果

前端传入sql语句和参数,支持全局变量、mybatis的xml语法

代码语言:javascript
复制
# sql
	select
            rtc.*,
            cu.user_name AS created_by_name,
            uu.user_name AS updated_by_name
        from ram_tmp_conf rtc
         LEFT JOIN ${db_dms}.base_user_info cu ON cu.user_id = rtc.created_by
         LEFT JOIN ${db_dms}.base_user_info uu ON uu.user_id = rtc.updated_by
        <trim prefix="where" prefixOverrides="and | or">
            <if test="tableName != null and tableName != ''">
                AND rtc.table_name like concat('%',#{tableName},'%')
            </if>
        </trim>

后端调用

image-1661063971086
image-1661063971086

日志输出

image-1661064239785
image-1661064239785

结果返回

代码语言:javascript
复制
{
  "code": 0,
  "data": {
    "iPage": {
      "countId": "",
      "current": 1,
      "hitCount": false,
      "maxLimit": null,
      "optimizeCountSql": true,
      "orders": [],
      "pages": 1,
      "records": [
        {
          "updatedTime": "2022-08-17 17:31:54",
          "createdByName": "张学胜",
          "updatedBy": "3333",
          "agmtTypeId": "1559835398878855168",
          "isValid": "1",
          "updatedByName": "张学胜",
          "tableName": "TEM_001",
          "agmtTmpAddr": "",
          "agmtTypeName": "协议模板001",
          "createdBy": "3333",
          "agmtTypeRemark": "协议模板001",
          "agmtTypeSql": "SELECT * FROM TEM_001;",
          "createdTime": "2022-08-17 17:31:54",
          "importTmpAddr": ""
        }
      ],
      "searchCount": true,
      "size": 1,
      "total": 1
    },
    "list": [
      {
        "updatedTime": "2022-08-17 17:31:54",
        "createdByName": "张学胜",
        "updatedBy": "3333",
        "agmtTypeId": "1559835398878855168",
        "isValid": "1",
        "updatedByName": "张学胜",
        "tableName": "TEM_001",
        "agmtTmpAddr": "",
        "agmtTypeName": "协议模板001",
        "createdBy": "3333",
        "agmtTypeRemark": "协议模板001",
        "agmtTypeSql": "SELECT * FROM TEM_001;",
        "createdTime": "2022-08-17 17:31:54",
        "importTmpAddr": ""
      }
    ]
  },
  "isImport": false,
  "maxWidth": {},
  "msg": "",
  "success": 1
}

可以看到,没有问题

工具类分享

代码语言:javascript
复制
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.StaticLog;
import com.amazonaws.opendistro.elasticsearch.sql.jdbc.shadow.com.amazonaws.util.StringInputStream;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eye.channelflow.core.vo.MsgException;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
import org.apache.ibatis.builder.xml.XMLStatementBuilder;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.parsing.XPathParser;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.List;
import java.util.Map;

/**
 * Mybatis构建sql工具类
 * Created by GMQ on 2022/8/20 14:39
 */
@Component
public class MybatisUtil {

    @Autowired
    SqlSession sqlSession;

    /**
     * 执行sql, 支持mybatis mapper.xml语法
     *
     * @param sql       执行的sql表达式
     * @param parameter 参数
     * @return
     */
    public List<Map<String, Object>> query(String sql, Map<String, Object> parameter) {
        List<Map<String, Object>> result = null;
        try {
            Configuration configuration = sqlSession.getConfiguration();
            StaticLog.info("sql:{}", sql);
            String uuid = IdUtil.fastSimpleUUID();
            StringInputStream inputStream = new StringInputStream("<?xml version=\"1.0\" encoding=\"UTF-8\" ?> <!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" > <mapper> <select id=\"" + uuid + "\" resultType=\"java.util.Map\"> " + sql + " </select> </mapper>");
            XPathParser parser = new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver());
            XNode node = parser.evalNode("/mapper").evalNodes("select").get(0);
            XMLStatementBuilder xmlStatementBuilder = new XMLStatementBuilder(configuration, new MapperBuilderAssistant(configuration, inputStream.toString()), node, null);
            xmlStatementBuilder.parseStatementNode();
            Executor executor = newExecutor(configuration);
            MappedStatement mappedStatement = configuration.getMappedStatement(uuid);

            StaticLog.info("==> Preparing: {}", mappedStatement.getBoundSql(parameter).getSql());
            StaticLog.info("==> Parameters: {}", mappedStatement.getBoundSql(parameter).getParameterObject());
            result = executor.query(mappedStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
        } catch (Exception e) {
            StaticLog.error("sql执行错误: ", e.getMessage());
            e.printStackTrace();
            throw new MsgException("sql执行错误");
        }
        return result;
    }

    /**
     * 分页查询
     *
     * @param page
     * @param sql
     * @param parameter
     * @return com.baomidou.mybatisplus.core.metadata.IPage<java.util.Map>
     * @throws
     * @author GMQ
     * @date 2022/8/21 11:59
     **/
    public IPage<Map> queryPage(Page page, String sql, Map<String, Object> parameter) {
        IPage<Map> iPage = page;
        try {
            Configuration configuration = sqlSession.getConfiguration();
            String uuid = IdUtil.fastSimpleUUID();
            String countSql = StrUtil.format("select count(*) from ( {} ) count_select", sql);
            StaticLog.info("countSql:{}", countSql);
            StringInputStream inputStream = new StringInputStream("<?xml version=\"1.0\" encoding=\"UTF-8\" ?> <!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" > <mapper> <select id=\"" + uuid + "\" resultType=\"java.lang.Integer\"> " + countSql + " </select> </mapper>");
            XPathParser parser = new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver());
            XNode node = parser.evalNode("/mapper").evalNodes("select").get(0);
            XMLStatementBuilder xmlStatementBuilder = new XMLStatementBuilder(configuration, new MapperBuilderAssistant(configuration, inputStream.toString()), node, null);
            xmlStatementBuilder.parseStatementNode();
            Executor executor = newExecutor(configuration);
            MappedStatement mappedStatement = configuration.getMappedStatement(uuid);

            StaticLog.info("==> Preparing: {}", mappedStatement.getBoundSql(parameter).getSql());
            StaticLog.info("==> Parameters: {}", mappedStatement.getBoundSql(parameter).getParameterObject());
            Object result = executor.query(mappedStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER).get(0);
            page.setTotal(result == null ? 0L : Long.parseLong(result.toString()));
            if (page.getTotal() > 0) {
                page.setRecords(query(StrUtil.format("{} limit {},{}", sql, page.offset(), page.getSize()), parameter));
            }
        } catch (Exception e) {
            StaticLog.error("sql执行错误: ", e.getMessage());
            throw new MsgException("sql执行错误");
        }
        return iPage;
    }


    private Executor newExecutor(Configuration configuration) {
        final Environment environment = configuration.getEnvironment();
        if (environment == null) {
            throw new ExecutorException("ResultLoader could not load lazily.  Environment was not configured.");
        }
        final DataSource ds = environment.getDataSource();
        if (ds == null) {
            throw new ExecutorException("ResultLoader could not load lazily.  DataSource was not configured.");
        }
        final TransactionFactory transactionFactory = environment.getTransactionFactory();
        final Transaction tx = transactionFactory.newTransaction(ds, null, false);
        return configuration.newExecutor(tx, ExecutorType.SIMPLE);
    }

}

依赖hutool工具类,可自己实现修改

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 先看效果
  • 工具类分享
相关产品与服务
Elasticsearch Service
腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档