精华内容
下载资源
问答
  • mybatis获取mapper执行SQL语句

    万次阅读 2018-08-19 15:45:23
    最近提的一个需求,就是要记录起来mapper里面执行了哪些SQL语句,用来分析SQL语句执行的快慢。然后我就研究了一下,如何获取mapper.xml里面运行的SQL语句。 主要就是一句代码: //这里面值填了一个参数,这个...

    “人不寐,将军白发征夫泪”
    最近提的一个需求,就是要记录起来mapper里面执行了哪些SQL语句,用来分析SQL语句执行的快慢。然后我就研究了一下,如何获取到 mapper.xml里面运行的SQL语句。
    主要就是一句代码:

    //这里面值填了一个参数,这个参数的意思是:com.demo.db.mapper.DemoMapper是xml文件里的namespace路径。
    //insert是你的id,即<insert id="insert">
    String sql = sqlSessionFactory.getConfiguration().getMappedStatement("com.demo.db.mapper.DemoMapper.insert").getBoundSql().getSql();

    那么sqlSessionFactory该如何获取呢?一般的,如果配置了mybatis mapper 扫描器,就可以直接在代码中注入进来,即@Autowired
    private SqlSessionFactory sqlSessionFactory;

    然后,getMappedStatement方法是什么意思呢?我们查看源代码得知:
    这里写图片描述
    还有,就是上面的getBoundSql() 方法,里面是可以传参数的,也可以不传,参数可以是该SQL语句参数类。如下图:
    这里写图片描述

    展开全文
  • 1.背景 工作的时候遇到一个这样的需要,在多机环境下,使用Mysql作为参数...为了保证各个Mysql数据的同步,有一个Log表,用于记录操作主Mysql的SQL语句,从而其他备Mysql只需要通过Log表来进行数据同步。 2.难点 ...

    1.背景

    工作的时候遇到一个这样的需要,在多机环境下,使用Mysql作为参数库。因为某些原因不能使用Mysql自带的数据同步,所以需要自己实现一个多节点的Mysql数据同步程序。

    所以打算人为的设定主Mysql可读可写,备Mysql只能读。为了保证各个Mysql数据的同步,有一个Log表,用于记录操作主Mysql的SQL语句,从而其他备Mysql只需要通过Log表来进行数据同步。

    更新:本文章已替换成自定义注解的模式(上版本是基于指定方法名作为切入点)

    2.难点

    (1)由于项目使用的是Mybatis,不是使用原生的jdbc,所以需要在不影响其他人使用Mybatis开发的同时,获取SQL语句并写入log表

    (2)需要保证mapper的操作和log的insert在同一个事务中

    3.实现

    3.1ModelSumbit.java

    自定义注解,用于Aop切入点

    package com.yjy.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ModelSumbit{
       
        String value() default "";
    }

    3.2LogAdvice.java

    主要看环绕通知方法

    package com.lyf.aspect;
    
    import com.lyf.service.LogService;
    import com.lyf.utils.SqlUtils;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    
    
    @Aspect
    @Component
    public class MyAdvice {
    
        @Autowired
        private LogService logService;
    
        @Autowired
        private SqlSessionFactory sqlSessionFactory;
    
    
        @Pointcut("@annotation(com.yjy.annotation.ModelSumbit)")
        private void pc(){
    
        }
    
        //前置通知
        //指定该方法是前置通知,并指定切入点
        @Before("MyAdvice.pc()")
        public void before(){
    //        System.out.println("这是前置通知!!!!!");
        }
    
        //后置通知
        @AfterReturning("MyAdvice.pc()")
        public void afterReturning(){
    //        System.out.println("这是后置通知!(如果出现异常,将不会调用)!!!!");
        }
    
        //环绕通知
        @Around("MyAdvice.pc()")
        public Object around(ProceedingJoinPoint pjp) throws Throwable{
            //1.从redis中获取主数据库,若获取不到直接退出,否则判断当前数据源是会否为主,若不为主,则切换到主数据源
            //2.调用目标方法
            Object proceed = pjp.proceed();
            //3.获取SQL
            String sql = SqlUtils.getMybatisSql(pjp,sqlSessionFactory);
            System.out.println(sql);
            //4.插入日志
            logService.insert(sql);
            //5.通知同步程序
            return proceed;
        }
    
        //异常通知
        @AfterThrowing("MyAdvice.pc()")
        public void afterException(){
    //        System.out.println("出事了,抛异常了!!!!");
        }
    
        //后置通知
        @After("MyAdvice.pc()")
        public void after(){
    //        System.out.println("这是后置通知!(无论是否出现异常都会调用)!!!!");
        }
    }

    3.3SqlUtils.java

    用于获取SQL语句

    package com.lyf.utils;
    
    import com.sun.deploy.util.ArrayUtil;
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.mapping.ParameterMapping;
    import org.apache.ibatis.reflection.MetaObject;
    import org.apache.ibatis.session.Configuration;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.type.TypeHandlerRegistry;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.reflect.MethodSignature;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Parameter;
    import java.text.DateFormat;
    import java.util.*;
    
    public class SqlUtils {
    
        /**
         * 获取aop中的SQL语句
         * @param pjp
         * @param sqlSessionFactory
         * @return
         * @throws IllegalAccessException
         */
        public static String getMybatisSql(ProceedingJoinPoint pjp, SqlSessionFactory sqlSessionFactory) throws IllegalAccessException {
            Map<String,Object> map = new HashMap<>();
            //1.获取namespace+methdoName
            MethodSignature signature = (MethodSignature) pjp.getSignature();
            Method method = signature.getMethod();
            String namespace = method.getDeclaringClass().getName();
            String methodName = method.getName();
            //2.根据namespace+methdoName获取相对应的MappedStatement
            Configuration configuration = sqlSessionFactory.getConfiguration();
            MappedStatement mappedStatement = configuration.getMappedStatement(namespace+"."+methodName);
    //        //3.获取方法参数列表名
    //        Parameter[] parameters = method.getParameters();
            //4.形参和实参的映射
            Object[] objects = pjp.getArgs(); //获取实参
            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
            for (int i = 0;i<parameterAnnotations.length;i++){
                Object object = objects[i];
                if (parameterAnnotations[i].length == 0){ //说明该参数没有注解,此时该参数可能是实体类,也可能是Map,也可能只是单参数
                    if (object.getClass().getClassLoader() == null && object instanceof Map){
                        map.putAll((Map<? extends String, ?>) object);
                        System.out.println("该对象为Map");
                    }else{//形参为自定义实体类
                        map.putAll(objectToMap(object));
                        System.out.println("该对象为用户自定义的对象");
                    }
                }else{//说明该参数有注解,且必须为@Param
                    for (Annotation annotation : parameterAnnotations[i]){
                        if (annotation instanceof Param){
                            map.put(((Param) annotation).value(),object);
                        }
                    }
                }
            }
            //5.获取boundSql
            BoundSql boundSql = mappedStatement.getBoundSql(map);
            return showSql(configuration,boundSql);
        }
    
        /**
         * 解析BoundSql,生成不含占位符的SQL语句
         * @param configuration
         * @param boundSql
         * @return
         */
        private  static String showSql(Configuration configuration, BoundSql boundSql) {
            Object parameterObject = boundSql.getParameterObject();
            List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
            String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
            if (parameterMappings.size() > 0 && parameterObject != null) {
                TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
                if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                    sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));
                } else {
                    MetaObject metaObject = configuration.newMetaObject(parameterObject);
                    for (ParameterMapping parameterMapping : parameterMappings) {
                        String propertyName = parameterMapping.getProperty();
                        String[] s =  metaObject.getObjectWrapper().getGetterNames();
                        s.toString();
                        if (metaObject.hasGetter(propertyName)) {
                            Object obj = metaObject.getValue(propertyName);
                            sql = sql.replaceFirst("\\?", getParameterValue(obj));
                        } else if (boundSql.hasAdditionalParameter(propertyName)) {
                            Object obj = boundSql.getAdditionalParameter(propertyName);
                            sql = sql.replaceFirst("\\?", getParameterValue(obj));
                        }
                    }
                }
            }
            return sql;
        }
    
        /**
         * 若为字符串或者日期类型,则在参数两边添加''
         * @param obj
         * @return
         */
        private static String getParameterValue(Object obj) {
            String value = null;
            if (obj instanceof String) {
                value = "'" + obj.toString() + "'";
            } else if (obj instanceof Date) {
                DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
                value = "'" + formatter.format(new Date()) + "'";
            } else {
                if (obj != null) {
                    value = obj.toString();
                } else {
                    value = "";
                }
            }
            return value;
        }
    
        /**
         * 获取利用反射获取类里面的值和名称
         *
         * @param obj
         * @return
         * @throws IllegalAccessException
         */
        private static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {
            Map<String, Object> map = new HashMap<>();
            Class<?> clazz = obj.getClass();
            System.out.println(clazz);
            for (Field field : clazz.getDeclaredFields()) {
                field.setAccessible(true);
                String fieldName = field.getName();
                Object value = field.get(obj);
                map.put(fieldName, value);
            }
            return map;
        }
    }
    

    4.注意事项

    1. Mapper接口的增删改方法上面加上@ModelSumbit注解,才会进入模型数据提交AOP
    2. Mapper接口方法的形参,可以有如下三种形式

    ①形参为自定义实体类

    @ModelSumbit
    void insert(User user);

    ②形参为Map

    @ModelSumbit
    void insert(Map<String,Object> map);

    ③形参为单个或多个参数,需要使用@Param注解

    @ModelSumbit
    void insert(@Param("userName") String userName, @Param("age")Integer age);

    注意:即便只有一个参数,采用第③方式的时候,仍然需要使用@Param注解

    展开全文
  • Mybatis mapper获取sql

    千次阅读 2016-11-28 22:30:03
    Mybatis mapper获取sql 今天花了点时间,在网上找了mybatis获取执行sql的工具类,觉得工具类写的挺好的。获取sql的目的是想做异步的导入导出,在页面点击导入导出时,根据页面的参数和后台mybaitis要执行的sql组合...

    今天花了点时间,在网上找了mybatis获取执行sql的工具类,觉得工具类写的挺好的。获取sql的目的是想做异步的导入导出,在页面点击导入导出时,根据页面的参数和后台mybaitis要执行的sql组合成一个完整的执行sql入库,另外一个服务则读取这个sql去做导入导出的相关操作。
    如果已经有消息服务的基础,这两个服务可以通过消息中间件来通讯。页面导入导出时,保存sql及发送消息到另外的服务,导入导出服务收到消息执行处理,完成后通过消息反馈给页面,导入服务则反馈导入成功与否,导出服务则执行生成下载文件的链接,反馈给页面。

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class MyBatisSql {
    
        /**
         * 运行期 sql
         */
        private String sql;
    
        /**
         * 参数 数组
         */
        private Object[] parameters;
    
        public void setSql(String sql) {
            this.sql = sql;
        }
    
        public String getSql() {
            return sql;
        }
    
        public void setParameters(Object[] parameters) {
            this.parameters = parameters;
        }
    
        public Object[] getParameters() {
            return parameters;
        }
    
        @Override
        public String toString() {
            if (parameters == null || sql == null) {
                return "";
            }
            List<Object> parametersArray = Arrays.asList(parameters);
            List<Object> list = new ArrayList<Object>(parametersArray);
            while (sql.indexOf("?") != -1 && list.size() > 0 && parameters.length > 0) {
                sql = sql.replaceFirst("\\?", list.get(0).toString());
                list.remove(0);
            }
            return sql.replaceAll("(\r?\n(\\s*\r?\n)+)", "\r\n");
        }
    
    }
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.mapping.ParameterMapping;
    import org.apache.ibatis.mapping.ParameterMode;
    import org.apache.ibatis.reflection.MetaObject;
    import org.apache.ibatis.reflection.property.PropertyTokenizer;
    import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
    import org.apache.ibatis.session.Configuration;
    import org.apache.ibatis.session.SqlSessionFactory;
    
    import java.util.List;
    import java.util.Map;
    
    public class MyBatisSqlUtils {
        /**
         * 运行期获取MyBatis执行的SQL及参数
         *
         * @param id                Mapper xml 文件里的select Id
         * @param parameterMap      参数
         * @param sqlSessionFactory
         * @return
         */
        public static MyBatisSql getMyBatisSql(String id, Map<String, Object> parameterMap, SqlSessionFactory sqlSessionFactory) {
            MyBatisSql ibatisSql = new MyBatisSql();
            MappedStatement ms = sqlSessionFactory.getConfiguration().getMappedStatement(id);
            BoundSql boundSql = ms.getBoundSql(parameterMap);
            ibatisSql.setSql(boundSql.getSql());
            List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
            Configuration configuration = sqlSessionFactory.getConfiguration();
            if (parameterMappings != null) {
                Object[] parameterArray = new Object[parameterMappings.size()];
                ParameterMapping parameterMapping = null;
                Object value = null;
                Object parameterObject = null;
                MetaObject metaObject = null;
                PropertyTokenizer prop = null;
                String propertyName = null;
                String[] names = null;
                for (int i = 0; i < parameterMappings.size(); i++) {
                    parameterMapping = parameterMappings.get(i);
                    if (parameterMapping.getMode() != ParameterMode.OUT) {
                        propertyName = parameterMapping.getProperty();
                        names = propertyName.split("\\.");
                        if (propertyName.indexOf(".") != -1 && names.length == 2) {
                            parameterObject = parameterMap.get(names[0]);
                            propertyName = names[1];
                        } else if (propertyName.indexOf(".") != -1 && names.length == 3) {
                            parameterObject = parameterMap.get(names[0]); // map
                            if (parameterObject instanceof Map) {
                                parameterObject = ((Map) parameterObject).get(names[1]);
                            }
                            propertyName = names[2];
                        } else {
                            parameterObject = parameterMap.get(propertyName);
                        }
                        metaObject = parameterMap == null ? null : MetaObject.forObject(parameterObject,configuration.getObjectFactory(),configuration.getObjectWrapperFactory(), configuration.getReflectorFactory());
                        prop = new PropertyTokenizer(propertyName);
                        if (parameterObject == null) {
                            value = null;
                        } else if (ms.getConfiguration().getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass())) {
                            value = parameterObject;
                        } else if (boundSql.hasAdditionalParameter(propertyName)) {
                            value = boundSql.getAdditionalParameter(propertyName);
                        } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) {
                            value = boundSql.getAdditionalParameter(prop.getName());
                            if (value != null) {
                                value = MetaObject.forObject(value,configuration.getObjectFactory(),configuration.getObjectWrapperFactory(), configuration.getReflectorFactory()).getValue(propertyName.substring(prop.getName().length()));
                            }
                        } else {
                            value = metaObject == null ? null : metaObject.getValue(propertyName);
                        }
                        parameterArray[i] = value;
                    }
                }
                ibatisSql.setParameters(parameterArray);
            }
            return ibatisSql;
        }
    
    }

    上面就是两个主要的实现获取mybatis 执行sql的代码,也是在网上搜索的,这里要感谢作者,我忘了贴原文链接了,后面记得补上,呵呵。。

    展开全文
  • MyBatis直接执行SQL的工具SqlMapper

    万次阅读 热门讨论 2015-03-11 09:47:02
    为了让通用Mapper更彻底的支持多表操作以及更灵活的操作,在2.2.0版本增加了一个可以直接执行SQL的新类SqlMapper。通过这篇博客,我们来了解一下SqlMapper。SqlMapper提供的方法SqlMapper提供了以下这些公共方法: ...

    可能有些人也有过类似需求,一般都会选择使用其他的方式如Spring-JDBC等方式解决。

    能否通过MyBatis实现这样的功能呢?

    为了让通用Mapper更彻底的支持多表操作以及更灵活的操作,在2.2.0版本增加了一个可以直接执行SQL的新类SqlMapper

    通过这篇博客,我们来了解一下SqlMapper

    SqlMapper提供的方法

    SqlMapper提供了以下这些公共方法:

    • Map<String,Object> selectOne(String sql)

    • Map<String,Object> selectOne(String sql, Object value)

    • <T> T selectOne(String sql, Class<T> resultType)

    • <T> T selectOne(String sql, Object value, Class<T> resultType)

    • List<Map<String,Object>> selectList(String sql)

    • List<Map<String,Object>> selectList(String sql, Object value)

    • <T> List<T> selectList(String sql, Class<T> resultType)

    • <T> List<T> selectList(String sql, Object value, Class<T> resultType)

    • int insert(String sql)

    • int insert(String sql, Object value)

    • int update(String sql)

    • int update(String sql, Object value)

    • int delete(String sql)

    • int delete(String sql, Object value)

    一共14个方法,这些方法的命名和参数和SqlSession接口的很像,只是基本上第一个参数都成了sql。

    其中Object value为入参,入参形式和SqlSession中的入参一样,带有入参的方法,在使用时sql可以包含#{param}${param}形式的参数,这些参数需要通过入参来传值。需要的参数过多的时候,参数可以使用Map类型。另外这种情况下的sql还支持下面这种复杂形式:

    String sql = "<script>select * from sys_user where 1=1"  + 
            "<if test=\"usertype != null\">usertype = #{usertype}</if></script>";

    这种情况用的比较少,不多说。

    不带有Object value的所有方法,sql中如果有参数需要手动拼接成一个可以直接执行的sql语句。

    selectXXX方法中,使用Class<T> resultType可以指定返回类型,否则就是Map<String,Object>类型。

    实例化SqlMapper

    SqlMapper构造参数public SqlMapper(SqlSession sqlSession),需要一个入参SqlSession sqlSession,在一般系统中,可以按照下面的方式获取:

    SqlSession sqlSession = (...);//通过某些方法获取sqlSession
    //创建sqlMapper
    SqlMapper sqlMapper = new SqlMapper(sqlSession);

    如果使用的Spring,那么可以按照下面的方式配置<bean>:

    <bean id="sqlMapper" class="com.github.abel533.sql.SqlMapper" scope="prototype">
      <constructor-arg ref="sqlSession"/>
    </bean>

    在Service中使用的时候可以直接使用@Autowired注入。

    简单例子

    src/test/java目录的com.github.abel533.sql包中包含这些方法的测试。

    下面挑几个看看如何使用。

    selectList

    //查询,返回List<Map>
    List<Map<String, Object>> list = sqlMapper.selectList("select * from country where id < 11");
    
    //查询,返回指定的实体类
    List<Country> countryList = sqlMapper.selectList("select * from country where id < 11", Country.class);
    
    //查询,带参数
    countryList = sqlMapper.selectList("select * from country where id < #{id}", 11, Country.class);
    
    //复杂点的查询,这里参数和上面不同的地方,在于传入了一个对象
    Country country = new Country();
    country.setId(11);
    countryList = sqlMapper.selectList("<script>" +
            "select * from country " +
            "   <where>" +
            "       <if test=\"id != null\">" +
            "           id &lt; #{id}" +
            "       </if>" +
            "   </where>" +
            "</script>", country, Country.class);

    selectOne

    Map<String, Object> map = sqlMapper.selectOne("select * from country where id = 35");
    
    map = sqlMapper.selectOne("select * from country where id = #{id}", 35);
    
    Country country = sqlMapper.selectOne("select * from country where id = 35", Country.class);
    
    country = sqlMapper.selectOne("select * from country where id = #{id}", 35, Country.class);

    insert,update,delete

    //insert
    int result = sqlMapper.insert("insert into country values(1921,'天朝','TC')");
    
    Country tc = new Country();
    tc.setId(1921);
    tc.setCountryname("天朝");
    tc.setCountrycode("TC");
    //注意这里的countrycode和countryname故意写反的
    result = sqlMapper.insert("insert into country values(#{id},#{countrycode},#{countryname})"
                              , tc);
    
    
    //update
    result = sqlMapper.update("update country set countryname = '天朝' where id = 35");
    
    tc = new Country();
    tc.setId(35);
    tc.setCountryname("天朝");
    
    int result = sqlMapper.update("update country set countryname = #{countryname}" + 
               " where id in(select id from country where countryname like 'A%')", tc);
    
    
    //delete
    result = sqlMapper.delete("delete from country where id = 35");
    result = sqlMapper.delete("delete from country where id = #{id}", 35);
    

    注意

    通过上面这些例子应该能对此有个基本的了解,但是如果你使用参数方式,建议阅读下面的文章:

    深入了解MyBatis参数

    实现原理

    2015-03-09:最初想要设计这个功能的时候,感觉会很复杂,想的也复杂,需要很多个类,因此当时没有实现。

    2015-03-10:突发奇想,设计了现在的这种方式。并且有种强烈的感觉就是幸好昨天没有尝试去实现,因为昨天晚上思考这个问题的时候是晚上10点多,而今天(10号)是晚上7点开始思考。我很庆幸在一个更清醒的状态下去写这段代码。

    下面简单说思路和实现方式。

    在写MyBatis分页插件的时候熟悉了MappedStatement类。

    在写通用Mapper的时候熟悉了xmlSqlNode结构。

    如果我根据SQL动态的创建一个MappedStatement,然后使用MappedStatementidsqlSession中执行不就可以了吗?

    想到这一点,一切就简单了。

    看看下面select查询创建MappedStatement的代码:

    /**
     * 创建一个查询的MS
     *
     * @param msId
     * @param sqlSource 执行的sqlSource
     * @param resultType 返回的结果类型
     */
    private void newSelectMappedStatement(String msId, SqlSource sqlSource, final Class<?> resultType) {
        MappedStatement ms = new MappedStatement.Builder(
                configuration, msId, sqlSource, SqlCommandType.SELECT)
            .resultMaps(new ArrayList<ResultMap>() {
                {
                    add(new ResultMap.Builder(configuration,
                            "defaultResultMap",
                            resultType,
                            new ArrayList<ResultMapping>(0)).build());
                }
            })
            .build();
        //缓存
        configuration.addMappedStatement(ms);
    }

    代码是不是很简单,这段代码的关键是参数sqlSource,下面是创建SqlSource的方法,分为两种。

    一种是一个完整的sql,不需要参数的,可以直接执行的:

    StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);

    其中configurationsqlSession中获取,sql就是用户传入到sql语句,是不是也很简单?

    另一种是支持动态sql的,支持参数的SqlSource

    SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);

    是不是也很简单?这个方法其实可以兼容上面的StaticSqlSource,这里比上面多了一个parameterType,因为这儿是可以传递参数的,另外languageDriver是从configuration中获取的。

    是不是很简单?

    我一开始也没想到MyBatis直接执行sql实现起来会这么的容易。

    insert,delete,update方法的创建更容易,因为他们的返回值都是int,所以处理起来更简单,有兴趣的可以查看SqlMapper的源码。

    https://gitee.com/free/Mybatis_Utils/tree/master/SqlMapper

    展开全文
  • 问题 最近开发新功能,调试 mapper.xml 里的SQL,遇到...总之就是不知道数据库执行了什么SQL。 解决 需要初始化 SqlSessionFactory 对象,这样才能读取 mapper.xml 文件: @Bean(name = "sqlSessionFactory") public
  • springboot对mapper切面,获取mybatis执行sql

    千次阅读 热门讨论 2020-02-19 14:56:53
    工作需要,有个需求是这样子的:输入接口地址,能查询出他调用了哪些sql,因此才有了本文章 采用切面方式,代码如下 ServiceAspect import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.session....
  • 文章目录MyBatis源码分析调用Mapper接口方法执行SQL整体操作流程相关参考 MyBatis源码分析 调用Mapper接口方法执行SQL 在第二组测试代码中,通过SqlSession.getMapper()方法获取自定义Mapper接口,并通过执行Mapper...
  • [JAVA] mappersql校验

    2019-07-08 15:12:49
    mappersql校验,在项目启动前进行sql语法校验,通常要到执行这个mapper才会报错。 package ix.account.util; import com.alibaba.druid.sql.ast.SQLStatement; import ...
  • hello~各位读者好,我是鸭血粉丝(大家可以称呼我为「阿粉」)。今天,阿粉带着大家来了解一下获取 mapper.xml 配置文件中的sql上期回顾首先,我们还是回顾一下上篇文件的内容。...
  • (转)MyBatis获取执行SQL语句

    千次阅读 2019-07-02 14:21:05
    最近提的一个需求,就是要记录起来mapper里面执行了哪些SQL语句,用来分析SQL语句执行的快慢。然后我就研究了一下,如何获取mapper.xml里面运行的SQL语句。 主要就是一句代码: //这里面值填了一个参数,这个...
  • 切面+mybatis 实现mapper执行的每一条sql的日志记录参考来源 https://blog.csdn.net/sdzhangshulong/article/details/1043932441.普通切面编写2.日志表建立(比较简单,可以根据需求自定义表)3.修改环绕通知,加入...
  • sql装配,自己实现一个,通用mapper和mybatis-generator是两个东西各自功能不同,结合使用而已 通用mapper: 1,省略单表操作的xml 2,不必写实现类(用通用mapper的单表操作方法不用,用xml中sql(mybatis)也不用)...
  • mapper执行sql原因

    2021-06-29 16:51:49
    场景 同一个mapper方法,传入参数相同,结果确不同。 原理 可能在查询后,操作了源数据,在下一次查询的时候,因为传入参数相同,mybatis存在一级缓存,不会去查询数据库,会... 当执行SQL时候两次查询中间发生了增删改
  • 首先,要知道mybatis调用mapper再到执行SQL,mybatis肯定做了处理,将mapper转过了,那就是jdk动态代理,来看下实际项目中的具体实现 这里可以看到使用的是MapperProxy,这个类也在mybatis的jar包里,看下 进去...
  • BeetlSql中的Mapper

    千次阅读 2019-09-18 19:47:42
    BeetlSql支持Mapper,它可以将sql文件映射到一个interface接口。接口的方法名与sql文件的sqlid一一对应。接口必须实现BaseMapper接口(后面可以自定义一个Base接口),它提供内置的CRUD方法,如insert,unique,...
  • MyBatis执行SQL两种方式(SqlSession和Mapper接口) 先把上次介绍SQL映射时创建的role表,POJO,映射的接口和XML映射文件搬过来。 role表 CREATE TABLE `role` ( `id` BIGINT(20) NOT NULL, `role_name` VARCHAR...
  • 网上看了很多关于写mybatis的...最终发现mybatis执行sql有两种方式: 第一种就是SqlSession发送Sql; 主要就是“配置文件(xml)+映射文件(mapper)+实体类(pojo)+测试类(test)” Role role = (Role)sql...
  • 当我们通过DefaultSqlSession的Mapper方式操作数据库时使用如下api: <T> T getMapper(Class<T> type); 此方法返回一个实现了type接口的实现类的实力,我们分析一下此实力的创建过程。 public <T...
  • mybatis获取执行sql(以mysql为例)

    千次阅读 2020-08-12 23:28:56
    mybatis获取执行sql(以mysql为例) 准备工作 前提使用的ssm项目,一张demo表,字段id(int)主键自增,name(varchar) 准备好两个工具类 MyBatisSqlUtils package com.fcmap.ssm.config; import java.util.List; ...
  • 上一篇文章分析到mapper.xml中的sql标签对应的MappedStatement是如何初始化的,而之前也分析了Mapper接口是如何被加载的,那么问题来了,这两个是分别加载的到Configuration中的,那么问题来了,在使用过程中...
  • 在上一篇中,我们介绍了在SpringBoot容器中,Mybatis加载mapper interface的过程,但对于mapper加载的全过程,这仅仅完成了50%,剩下的50%就是mapper的关联XML配置文件的加载过程,本篇,我们将围绕下面两个问题进行...
  • 前面的内容以及可以获取sqlSession了,下面我们来看从sqlSession中获取mapper。关于mapper我们只定义了接口,没有实现类,通过源码分析我们知道mybatis使用动态代理为我们生成。所以首先来创建一个mapper代理类: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 53,450
精华内容 21,380
关键字:

获取mapper执行sql