MybatisPlus分页优化

在采用MyBatisPlus进行开发时,避免不了会引用其提供的分页插件,在引用的时候通过查看代码会发现,他的默认取值逻辑是先查出数据库中所有的数据,然后根据分页参数再取出其中的一页数据;
在一些数据量较大的地方这么拿数据明显不是最优解;
依据我们日常的习惯,肯定是会把分页直接放到sql中,直接查询出某一页的数据进行优化;
MyBatisPlus中提供了一个配置:

import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 

@Configuration
@MapperScan("com.szss.admin.dao.*")//如代码中有设置范围,则此处无需设置
public class MybatisPlusConfig {
 
    /**
     * mybatis-plus分页插件<br>
     * 文档:http://mp.baomidou.com<br>
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        return paginationInterceptor;
    }
 
}

如开放debugSql打印,可以看出前后的sql变化;
这个时候扫描路径下的所有分页都已完成了执行逻辑

获取MyBatis执行SQL

工具类实现代码片段

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    public String showSql(Class<?> cls,String methodName,Object param) {
        String absoluteMetgodName=getAbsoluteMetgodName(cls,methodName);
        MappedStatement mappedStatement=sqlSessionFactory.getConfiguration().getMappedStatement(absoluteMetgodName);
        Configuration configuration=mappedStatement.getConfiguration();
        BoundSql boundSql=mappedStatement.getBoundSql(param);
        Object parameterObject = boundSql.getParameterObject();
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
        //CollectionUtils如无对应pom引用可换其他方法,仅判空用
        if (CollectionUtils.isNotEmpty(parameterMappings)&& Objects.nonNull(parameterObject)) {
            TypeHandlerRegistry typeHandlerRegistry=configuration.getTypeHandlerRegistry();
            MetaObject metaObject=configuration.newMetaObject(parameterObject);

            //object取值判断逻辑参考mybatis源码ParameterHandler.setParameters()
            Object[] values=parameterMappings.stream().map(it->{
                String property=it.getProperty();
                Object result;
                if (boundSql.hasAdditionalParameter(property)){
                    result=boundSql.getAdditionalParameter(property);
                }else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())){
                    result=parameterObject;
                }else{
                    result=metaObject.getValue(property);
                }
                //Object转String并拼接进Sql的逻辑可根据自己业务修改或补充
                return getParameterValue(result);
            }).toArray();
            sql=String.format(sql.replace("?","%s"),values);
        }
        return sql;
    }

    private String getAbsoluteMetgodName(Class<?> cls,String mothodName){
        return cls.getCanonicalName()+"."+mothodName;
    }

    private String getParameterValue(Object obj) {
        String value = null;
        if (obj instanceof String) {
            value = "'" + obj.toString() + "'";
        } else if (obj instanceof Date) {
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            value="to_date('"+sdf.format(obj)+"','yyyy-mm-dd hh24:mi:ss')";
        } else {
            if (obj != null) {
                value = obj.toString();
            } else {
                value = "\'\'";
            }

        }
        return value;
    }

调用代码片段
xxx.class为对应mapper的文件名 read more

记一个BUG

在一次发包后,没有修改接口A的任何代码,但是接口A却不能正常返回数据,
INFO级别日志一切正常,后换为DEBUG级别日志,看到一些信息:
Could not find result map java.lang.String
于是全局扫描ResultMap标签,发现的确有一处代码写错了,位置就在A接口的下边,是一段正处于开发阶段的代码
错误的原因就是我在ResultMap中写了java.lang.String,改成ResultType后正常

造成错误的原因:
1.没有通过纯净分支发布服务,因为我所开发的服务一般都是由我发布的,所以一般情况下都是在我本地的分支上发布的,正在开发的时候需要发布的情况是会经常出现的;
2.不了解Mybatis的加载机制,没有很明确的了解到与A接口无关的代码也会影响到A接口的运行 read more

Spring集成MyBatis设置打印SQL日志

在开发过程中,如果使用MyBatis进行开发,sql是在xml文件进行维护的,我们无法通过DeBug拿到完整的执行sql;
在SpringBoot集成MyBatis的项目中,日志文件一般通过logback-spring.xml进行配置
在这个阶段,如果需要通过配置实现sql打印,则需要在与标签平级的位置添加如下信息:

<logger name="com.baomidou.mybatisplus" level="DEBUG"><!--引用的包路径,我这里引用的是MyBatisPlus-->
<logger name="java.sql.Connection" level="DEBUG">
<logger name="java.sql.Statement" level="DEBUG">
<logger name="java.sql.PreparedStatement" level="DEBUG">