`
m17189363841
  • 浏览: 13922 次
文章分类
社区版块
存档分类
最新评论

Mybatis 动态执行SQL语句

 
阅读更多

有很多的接口都只是执行个SQL查询之后就直接返回给前端,那么我们能不能把这些SQL保存在数据库中,调用一个固定的接口就能根据传参查询出想要的数据呢?或者当为了加减个字段就得修改代码重启服务的痛苦能不能减少点呢?下面就是方案。

调用直接传入SQL语句(可以选择存数据库)和参数,SQL语句写法和在XML内的写法保持一致即可,包括Mybatis标签等等,参数选择使用通用的Map,可以从接口接收任何参数,方法的返回值是List<Map>。

<dependency>
   <groupId>org.ow2.asm</groupId>
   <artifactId>asm</artifactId>
   <version>7.0</version>
</dependency>
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Map;
 
//from fhadmin.cn
@Component
@Slf4j
public class SqlExecutor {
 
    @Autowired
    private SqlSessionFactory sqlSessionFactory;
 
    public void parserString(String originSql,Map<String,Object> param) {
        StringBuilder builder = new StringBuilder();
        builder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
        builder.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\r\n");
        builder.append("<mapper namespace=\"cn.video.asm.TestMapper\">\r\n");
        builder.append("	 <select id=\"queryById\"  resultType=\"java.util.Map\">\r\n");
        builder.append(originSql);
        builder.append("	 </select>\r\n");
        builder.append("</mapper>");
        InputStream inputStream = new ByteArrayInputStream(builder.toString().getBytes());
        Configuration baseConfig = sqlSessionFactory.getConfiguration();
        // 不能使用原有的config对象加载,否则下次就不会重复加载导致传入的SQL语句不能切换
        // 也可以在这里指定数据源,从对应的数据源做查询动作
        Configuration configuration = new Configuration(baseConfig.getEnvironment());
        String resource = "resource";
        ErrorContext.instance().resource(resource);
        XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration,resource ,configuration.getSqlFragments());
        mapperParser.parse();
        SqlSession sqlSessionXML = new DefaultSqlSessionFactory(configuration).openSession();
        Object result = null;
        try {
            // 使用自定义的ClassLoader
            MyClassLoader loader = new MyClassLoader();
            // 生成二进制字节码
            byte[] bytes = MyClassLoader.dump();
            // 加载我们生成的 Mapper类
            Class<?> clazz = loader.defineClass("cn.video.asm.TestMapper", bytes);
            // 将生成的类对象加载到configuration中
            configuration.addMapper(clazz);
            Method query = clazz.getMethod("queryById", Map.class);
            // 这里就是通过类对象从configuration中获取对应的Mapper
            Object testMapper = sqlSessionXML.getMapper(clazz);
            result = query.invoke(testMapper, param);
        } catch (Exception e) {
            log.error("",e);
        }
        System.out.println("dyn : " + result);
    }
}

  

package cn.video.common;
 
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
 
import static jdk.internal.org.objectweb.asm.Opcodes.*;
 
//from fhadmin.cn
public class MyClassLoader extends ClassLoader {
 
    public static byte[] dump() {
        ClassWriter cw = new ClassWriter(0);
        cw.visit(52, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, "cn/video/asm/TestMapper", null, "java/lang/Object", null);
        cw.visitSource("TestMapper.java", null);
        {
            MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "queryById", "(Ljava/util/Map;)Ljava/util/List;", "(Ljava/util/Map;)Ljava/util/List<Ljava/lang/Object;>;", null);
            mv.visitEnd();
        }
        cw.visitEnd();
        return cw.toByteArray();
    }
 
    public Class<?> defineClass(String name, byte[] b) {
        // ClassLoader是个抽象类,而ClassLoader.defineClass 方法是protected的
        // 所以我们需要定义一个子类将这个方法暴露出来
        Class<?> clazz = super.findLoadedClass(name);
        if (clazz != null) {
            return clazz;
        }
        return super.defineClass(name, b, 0, b.length);
    }
}

 

 

分享到:
评论

相关推荐

    mybatis直接执行sql语句后续之一

    这篇博客“mybatis直接执行sql语句后续之一”可能探讨了如何在MyBatis中高效且有效地执行SQL操作。下面我们将深入探讨MyBatis的SQL执行机制及相关知识点。 首先,MyBatis的核心组件是SqlSessionFactory,它是创建...

    Mybatis执行SQL语句的方式

    Mybatis 执行 SQL 语句的方式 Mybatis 是一个基于 Java 的持久层框架,它提供了多种方式来执行 SQL 语句。在本文中,我们将介绍三种执行 SQL 语句的方式:通过 Mapper 接口、通过 XML 配置文件、通过 SqlSession ...

    原样输出mybatis的sql执行语句(mysql和oracle都可用).zip

    MyBatis通过动态SQL映射文件或注解来将Java代码与SQL语句关联起来,它的核心功能包括SQL语句的构建、参数绑定和结果映射。在默认情况下,MyBatis并不会直接打印出执行的SQL语句,因此我们需要开启日志功能以获取这些...

    详解MyBatis直接执行SQL查询及数据批量插入

    而`${}`则是直接替换为变量值,不进行预编译,适用于动态构建SQL语句,但需注意SQL注入风险。 - **resultType与resultMap**:如果SQL查询的列名与Java对象的属性名完全匹配,可以省略`resultMap`,直接使用`...

    mybatis动态SQL语句

    if 、where、set、trim、choose 、foreach等在mybatis中的具体用法,有具体实例可供参考,玩转mybatis

    mybatis 动态sql及参数传递

    在实际开发过程中,我们往往需要编写复杂的SQL语句,拼接稍有不注意就会导致错误,Mybatis给开发者提供了动态SQL,大大降低了拼接SQL导致的错误。 动态标签 if标签 if标签通常用那个胡where语句,update语句,insert...

    MyBatis 3 _ SQL 语句构建器1

    MyBatis 3 的 SQL 语句构建器是其核心特性之一,它提供了一种更加优雅、可读性更强的方式来构建动态 SQL。SQL 语句构建器支持多种风格的 SQL 编写,包括匿名内部类风格、Builder/Fluent 风格以及动态条件构建。 1. ...

    MyBatis动态拼接SQL

    动态SQL是MyBatis的一大特色,它使得我们能够在运行时根据条件构建SQL语句。MyBatis通过`&lt;if&gt;`, `&lt;choose&gt;`, `&lt;when&gt;`, `&lt;otherwise&gt;`, `&lt;where&gt;`, `&lt;set&gt;`, `&lt;foreach&gt;`等标签来实现动态SQL的构建。 1. `&lt;if&gt;`标签...

    MyBatis 执行动态 SQL语句详解

    在 MyBatis 中,动态 SQL 是一个强大的特性,允许我们在 XML 映射文件或注解中编写条件语句,根据运行时的参数来决定 SQL 的具体执行内容。下面我们将深入探讨如何在 MyBatis 中执行动态 SQL 语句。 首先,我们要...

    mybatis之动态SQL

    动态 SQL 是 MyBatis 的一大特色,它允许我们在运行时根据条件构建 SQL 语句,极大地提高了代码的可维护性和灵活性。 动态 SQL 在 MyBatis 中主要通过 XML 映射文件或者注解来实现。在 XML 映射文件中,我们可以...

    在mybatis执行SQL语句之前进行拦击处理实例

    MyBatis拦截器实践 - 在MyBatis执行SQL语句之前进行拦截处理实例 MyBatis作为一个流行的持久层框架,提供了强大的数据库交互能力,但是在某些特殊场景下,我们需要在MyBatis执行SQL语句之前进行拦截处理,这便需要...

    mybatis+spring 框架中配置日志中显示sql语句

    在MyBatis与Spring整合的框架中,为了便于调试和性能优化,我们常常需要在日志中打印出执行的SQL语句。以下是如何在这样的环境中配置日志来显示SQL语句的详细步骤。 首先,我们需要了解MyBatis的日志实现。MyBatis...

    mybatis慢SQL插件

    拦截器监控慢SQL并将完整的可执行的SQL语句打印在日志文件中,复制该SQL语句即可在数据库工具中执行。 使用方法: 找到你springboot项目中的配置文件,增加如下配置即可 application.yml 配置如下: sql: slow...

    Mybatis中执行String类型的自己拼写的sql,不执行配置文件中的sql

    在MyBatis框架中,有时候我们可能需要在代码中直接编写SQL语句,而不是通过XML配置文件来执行SQL。这种情况通常发生在动态SQL或者特定场景下的临时查询中。本篇文章将详细探讨如何在MyBatis中执行String类型的自定义...

    mybatis打印出sql

    在开发过程中,为了调试和优化SQL,有时我们需要查看MyBatis执行的SQL语句。本压缩包提供了一种方法来实现这个功能,主要依赖于Log4j日志框架。 Log4j是Apache的一个开源项目,它提供了灵活且强大的日志记录功能,...

    Mybatis动态sql语句的mapper.xml文件

    MyBatis 的动态 SQL 是一种强大的特性,它允许你在运行时根据条件构建 SQL ...动态SQL,它一般是根据用户输入或外部条件动态组合SQL语句块。动态SQL能灵活的发挥SQL强大的功能、方便解决一些其他方法难以解决的问题。

    MyBatis 动态 SQL 示例

    附件是MyBatis 动态 SQL 示例,MyBatis 是一个持久层框架,它允许用户在 XML 文件中编写动态 SQL 语句。MyBatis 的动态 SQL 功能非常强大,它允许开发者根据运行时的条件动态地生成 SQL 语句。这使得 MyBatis 能够...

    MyBatis 动态SQL示例

    附件是MyBatis 动态SQL示例,MyBatis 是一个持久层框架,它允许用户在 XML 文件中编写动态 SQL 语句。MyBatis 的动态 SQL 功能非常强大,它允许开发者根据运行时的条件动态地生成 SQL 语句。这使得 MyBatis 能够灵活...

    ideal mybatis打印sql插件

    把 mybatis 输出的sql日志还原成完整的sql语句。 将日志输出的sql语句中的问号 ? 替换成真正的参数值。 通过 "Tools -&gt; MyBatis Log Plugin" 菜单或快捷键 "Ctrl+Shift+Alt+O" 启用。 点击窗口左边的 "Filter" ...

    mybatis拦截器修改执行sql语句

    1.网上搜索了很多,几乎都是能修改sql, 但是修改后的sql不生效,还是执行原来的sql. 2.这个版本亲测可以生效。 3.支持分页查询

Global site tag (gtag.js) - Google Analytics