zoukankan      html  css  js  c++  java
  • Mybatis利用拦截器做统一分页

    mybatis利用拦截器做统一分页

    查询传递Page参数,或者传递继承Page的对象参数。拦截器查询记录之后,通过改造查询sql获取总记录数。赋值Page对象,返回。

    示例项目:https://github.com/windwant/spring-boot-service

    https://github.com/windwant/spring-dubbo-service/tree/master/spring-boot-server


    拦截器:

    package com.xxx;
    
    import com.xxx.Page;
    import org.apache.ibatis.executor.Executor;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.mapping.ParameterMapping;
    import org.apache.ibatis.plugin.*;
    import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
    import org.apache.ibatis.session.ResultHandler;
    import org.apache.ibatis.session.RowBounds;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.Properties;
    
    /** 
    */
    @Intercepts({//拦截query查询
        @Signature(type=Executor.class,method="query",args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class})
    })
    public class PageIntercept implements Interceptor {
    
        public static final Logger logger = LoggerFactory.getLogger(PageIntercept.class);
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            Object parameter = invocation.getArgs()[1];
            Object args = invocation.getArgs()[1];
    		Object returnValue = invocation.proceed();
            if(args instanceof Page && ((Page) args).isCount()){
                MappedStatement mappedStatement=(MappedStatement)invocation.getArgs()[0];
                BoundSql boundSql = mappedStatement.getBoundSql(parameter);
                String originalSql = boundSql.getSql().trim();
                Object parameterObject = boundSql.getParameterObject();
                if(parameterObject instanceof Page){
                    ((Page) parameterObject).setOffset(0);
                    ((Page) parameterObject).setLimit(Integer.MAX_VALUE/((Page) parameterObject).getPage());
                }
    
                String countSql = "SELECT COUNT(*) FROM (" + originalSql + ") aliasForPage";
                Connection connection=mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection();
    
                BoundSql countBS = copyFromBoundSql(mappedStatement, boundSql, countSql);
                DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, countBS);
                PreparedStatement countStmt = connection.prepareStatement(countSql);
                parameterHandler.setParameters(countStmt);
                ResultSet rs = countStmt.executeQuery();
                int total =0;
                if (rs.next()) {
                    total = rs.getInt(1);
                }
                rs.close();
                countStmt.close();
                connection.close();
                //分页计算
                ((Page) args).setTotal(total);
            }
    
    	return returnValue;
        }
    
    
        private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) {
            BoundSql newBoundSql = new BoundSql(ms.getConfiguration(),sql, boundSql.getParameterMappings(), boundSql.getParameterObject());
            for (ParameterMapping mapping : boundSql.getParameterMappings()) {
                String prop = mapping.getProperty();
                if (boundSql.hasAdditionalParameter(prop)) {
                    newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
                    }
                }
            return newBoundSql;
        }
    
    
    
        @Override
    	public Object plugin(Object target) {
    		 return Plugin.wrap(target, this);
    	}
    
    	@Override
    	public void setProperties(Properties properties) {
    
    	}
    
    }

    数据库配置:

    package com.xxx.config;
    
    import javax.sql.DataSource;
    
    import com.xxx.PageIntercept;
    import org.apache.ibatis.plugin.Interceptor;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    
    /**
    * @description 
    */
    
    @Configuration
    @MapperScan(basePackages = "com.xxx.dao", sqlSessionFactoryRef = "sqlSessionFactory")
    public class DBConfig {
    
    	private final static Logger logger = LoggerFactory.getLogger(DBConfig.class);
    	
    	@Bean(name = "dataSource")
        @ConfigurationProperties(prefix = "datasource.planes")
    	@Primary
        public DataSource dataSource() {
            return DataSourceBuilder.create().build();
        }
    	
    	@Bean(name = "sqlSessionFactory")
    	@Primary
        public SqlSessionFactory sqlSessionFactory() throws Exception {
            SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
            bean.setDataSource(dataSource());
            bean.setPlugins(new Interceptor[]{new PageIntercept()});
            return bean.getObject();
        }
    	
    	@Bean(name = "transactionManager")
    	@Primary
        public DataSourceTransactionManager transactionManager() {
            return new DataSourceTransactionManager(dataSource());
        }
    	
    }  

    Page对象:

    package com.xxx;
    
    import com.xxx.Constants;
    
    /**
     * Created by Administrator on 2018/1/5.
     */
    public class Page {
    
        private int offset = 0;
    
        private int limit = Constants.DEAFULT_PAGE_LIMIT;
    
        private int total = 0;
    
        private int page = 1;
    
        private boolean count = true;
    
        public boolean isCount() {
            return count;
        }
    
        public void setCount(boolean count) {
            this.count = count;
        }
    
        public Page(){}
    
        public Page(int offset, int limit){
            this. offset = offset;
            this.limit = limit;
        }
        public int getPage() {
            return page;
        }
    
        public void setPage(int page) {
            this.page = page < 1?1:page;
        }
    
        public int getOffset() {
            return (page - 1) * limit;
        }
    
        public void setOffset(int offset) {
            this.offset = offset;
        }
    
        public int getLimit() {
            return limit;
        }
    
        public void setLimit(int limit) {
            this.limit = limit;
        }
    
        public int getTotal() {
            return total;
        }
    
        public void setTotal(int total) {
            this.total = total;
        }
    }
    

      

     

     

  • 相关阅读:
    .Net EF中DbContext动态生成DbSet
    .net core 3.0 中间件或过滤器中读取post请求body方法
    Asp.Net Core 5 WebAPI发布后的Swagger不显示问题
    .net Core 使用Swagger 让某些接口不显示在文档
    C# Request.InputStream 读取输入流为空的原因处理
    ASP.NET 中的缓存
    缓存依赖(文件、数据库)
    NLTK基本使用
    NLTK基本使用
    NLTK的基本使用
  • 原文地址:https://www.cnblogs.com/niejunlei/p/8243264.html
Copyright © 2011-2022 走看看