mybatis (plus) 自定义分页查询

位置:首页>文章>详情   分类: 教程分享 > Java教程   阅读(1057)   2024-04-19 09:28:45

接上一篇:mybatis Interceptor拦截器实现自定义扩展查询兼容mybatis plus-左搜 (leftso.com)

这里进行自定义分页查询扩展,基于mybatis plus,同样适用于mybatis

mybatis (plus) 自定义分页拦截器

@Intercepts({
        @Signature(
                type = Executor.class,
                method = "query",
                args = {MappedStatement.class,Object.class, RowBounds.class, ResultHandler.class}
        )
})
@Slf4j
public class MybatisPageSelectFilterInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        //这个可以得到当前执行的sql语句在xml文件中配置的id的值
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        Object parameter = invocation.getArgs()[1];
        if (parameter instanceof Paging){
            PageData<?> page=new PageData<>();

            BoundSql boundSql = mappedStatement.getBoundSql(parameter);
            Paging<?> paging =(Paging<?>)boundSql.getParameterObject();

            page.setCurrent(paging.getPageNum());
            page.setSize(paging.getPageSize());

            Connection connection = mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection();

            long count=count(connection,boundSql,paging.getSelectFilter());
            page.setTotal(count);
            page.setPages(count%paging.getPageSize()==0?(count/ paging.getPageSize()):(count/ paging.getPageSize())+1);
            if (paging.getPageNum()<=page.getPages()&&paging.getPageNum()>0){
                //先处理统计
                dealSelectFilter(mappedStatement,parameter,paging.getSelectFilter(),invocation,paging);
                // 继续执行
                List result = (List)invocation.proceed();
                page.setRecords(result);
            }else{
                page.setRecords(new ArrayList<>());
            }
            return Arrays.asList(page);
        }
        // 继续执行
        Object result = invocation.proceed();
        return result;
    }

    public int count(Connection connection,BoundSql boundSql, SelectFilter selectFilter) {

        Class entityClass = selectFilter.getEntityClass();
        if (Objects.nonNull(entityClass)){
            Field[] declaredFields = entityClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                TableField tableField=(TableField) declaredField.getAnnotation(TableField.class);
                if (Objects.nonNull(tableField)){
                    String dbName=StringUtils.isEmpty(tableField.value())?declaredField.getName():tableField.value();
                    if (Objects.nonNull(tableField)){
                        TableLogic tableLogic=(TableLogic) declaredField.getAnnotation(TableLogic.class);
                        if (Objects.nonNull(tableLogic)){
                            selectFilter.buildWithWhere();
                            String sql = selectFilter.getSql();
                            if (!sql.contains(dbName)){
                                selectFilter.eq(dbName,0);
                            }
                        }
                    }
                }
            }
        }

        PreparedStatement countStmt = null;
        ResultSet rs = null;
        selectFilter.buildWithWhere();
        String sql = selectFilter.getSql();
        String countSql=boundSql.getSql().replaceAll("select.*from","select count(0) from ")+sql;
        log.info(countSql);
        log.info(Arrays.toString(selectFilter.getSqlParamsMap().values().toArray()));
        try {
            countStmt = connection.prepareStatement(countSql);
            Map sqlParamsMap = selectFilter.getSqlParamsMap();
            if (!CollectionUtils.isEmpty(sqlParamsMap)){
                int index = 1;//从1开始赋值
                for (Object value : sqlParamsMap.values()) {
                    countStmt.setObject(index,value);
                    index++;
                }
            }
            rs = countStmt.executeQuery();
            if (rs.next()) {
                return rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != countStmt) {
                    countStmt.close();
                }
                if (null != rs) {
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }


    private void dealSelectFilter(MappedStatement mappedStatement,Object parameter,SelectFilter selectFilter,Invocation invocation,Paging paging){
        BoundSql boundSql = mappedStatement.getBoundSql(parameter);
        String oldsql = boundSql.getSql();
        log.info("old:"+oldsql);

        Class entityClass = selectFilter.getEntityClass();
        if (Objects.nonNull(entityClass)){
            TableName tableNameAnnotation = (TableName) entityClass.getDeclaredAnnotation(TableName.class);
            String tableName = tableNameAnnotation.value();
            Matcher matcher = Pattern.compile("^select\\s+\\*\\s+from\\s+" + tableName).matcher(oldsql.toLowerCase());
            if (matcher.find()){
                StringBuffer sqlBuilder=new StringBuffer();
                Field[] declaredFields = entityClass.getDeclaredFields();
                sqlBuilder.append("select ");
                List<String> fields=new ArrayList<>();

                for (Field declaredField : declaredFields) {
                    String fieldName = declaredField.getName();
                    TableField tableField = declaredField.getAnnotation(TableField.class);
                    if (Objects.nonNull(tableField)&&tableField.exist()){
                        String name = declaredField.getName();
                        String dbName=StringUtils.isEmpty(tableField.value())?fieldName:tableField.value();
                        fields.add(dbName+" "+ name);
                    }
                    TableId tableId = declaredField.getAnnotation(TableId.class);
                    if (Objects.nonNull(tableId)){
                        fields.add(StringUtils.isEmpty(tableId.value())?fieldName: tableId.value()+" "+declaredField.getName());
                    }

                }
                String join = String.join(",", fields);
                sqlBuilder.append(join);
                sqlBuilder.append(" from ").append(tableName).append(" ");
                oldsql=sqlBuilder.toString();

                selectFilter.buildWithWhere();
            }
        }

        selectFilter.buildWithWhere();

        List<ParameterMapping> parameterMappingList=new ArrayList<>();

        for (Object key : selectFilter.getSqlParamsMap().keySet()) {
            parameterMappingList.add(new ParameterMapping.Builder(mappedStatement.getConfiguration(),"selectFilter.sqlParamsMap."+key,Object.class).build());
        }

        String dealSql=oldsql+selectFilter.getSql()+" limit "+(paging.getPageNum()-1)* paging.getPageSize()+","+paging.getPageSize();

        BoundSql newBoundSql = new BoundSql(mappedStatement.getConfiguration(), dealSql,
                parameterMappingList, boundSql.getParameterObject());
        MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql),selectFilter.getEntityClass());
        invocation.getArgs()[0] = newMs;
    }


    /**
     * 复制原始MappedStatement
     * @param ms
     * @param newSqlSource
     * @return
     */
    private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource,Class<?> entityClass) {
        MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource,
                ms.getSqlCommandType());
        builder.resource(ms.getResource());
        builder.fetchSize(ms.getFetchSize());
        builder.statementType(ms.getStatementType());
        builder.keyGenerator(ms.getKeyGenerator());
        if (ms.getKeyProperties() != null) {
            for (String keyProperty : ms.getKeyProperties()) {
                builder.keyProperty(keyProperty);
            }
        }
        builder.timeout(ms.getTimeout());
        builder.parameterMap(ms.getParameterMap());

        //设置返回列表类型为实体对象类型
        ResultMap resultMap=new ResultMap.Builder(ms.getConfiguration(),ms.getId(), entityClass,new ArrayList<>()).build();
        List<ResultMap> resultMaps=new ArrayList<>();
        resultMaps.add(resultMap);
        builder.resultMaps(resultMaps);

        builder.cache(ms.getCache());
        builder.useCache(ms.isUseCache());
        return builder.build();
    }

    public static class BoundSqlSqlSource implements SqlSource {
        BoundSql boundSql;

        public BoundSqlSqlSource(BoundSql boundSql) {
            this.boundSql = boundSql;
        }

        public BoundSql getBoundSql(Object parameterObject) {
            return boundSql;
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
}


拦截器注册:

@Configuration
public class MybatisSelectFilterConfiguration {
    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    @PostConstruct
    public void addInterceptor() {

        MybatisListSelectFilterInterceptor listSelectFilterInterceptor=new MybatisListSelectFilterInterceptor();
        MybatisPageSelectFilterInterceptor pageSelectFilterInterceptor=new MybatisPageSelectFilterInterceptor();
        sqlSessionFactoryList.forEach(sqlSessionFactory -> {
            sqlSessionFactory.getConfiguration().addInterceptor(listSelectFilterInterceptor);
            sqlSessionFactory.getConfiguration().addInterceptor(pageSelectFilterInterceptor);
        });
    }
}

 


mapper 代码:

 

    @Select("select * from cy_xlxw")
    PageData<Xlxw> page(Paging<Xlxw> paging);

 


 

 

地址:https://www.leftso.com/article/1029.html

相关阅读

接上一篇:mybatis Interceptor拦截器实现自定义扩展查询兼容mybatis plus-左搜 (leftso.com)这里进行自定义分页查询扩展,基于mybatis plus,同样...
mybatis Interceptor拦截器实现自定义扩展查询兼容mybatis plus @Intercepts({ @Signature(type = Executor.c...
MySQL分页_MySQL分页语句_MySQ如何使用limit分页,本博客将会详细讲解mysql中的分页查询。讲清楚MySQL如何编写分页查询语句。
mybatis plus 自增长主键如何获取注意在model对象里面配置以下注解即可在调用save()方法后通过对象get获取@TableId(type = IdType.AUTO) BigI...
mybatis plus 逻辑删除使用说明全局逻辑值配置,application.properties# 逻辑已删除值(默认为 1) mybatis-plus.global-config.db...
MyBatis Insert插入数据返回主键的几种模式支持,包括@Insert注解,mapper.xml sql语句。mybatis insert插入数据返回i
mybatis plus find_in_set 使用wrapper.apply(StrUtil.isNotBlank(clazz)," find_in_set('"+clazz+"',claz...
某些情况下,我们使用mybaties时需要使用IN(虽然IN数据多了效率不高,但是少量还是可以用得)条件查询,这时候我们就需要传递参数了,下面是mybaties处理IN条件得参数使用方法首先Ma...
mybatis事物访问数据库的一级缓存和二级缓存和刷新缓存
spring boot mybatis 整合使用讲解介绍,spring boot与MyBatis的使用讲解介绍。spring boot mybatis xml mapper方式的入门和通过一个简...