自己现实mybatis分页插件 整合springboot 运行

本文档介绍了如何将自定义的Mybatis分页插件与SpringBoot进行整合,通过拦截器实现分页功能。参考了一篇CSDN博客,详细讲解了插件的拦截器实现及利用反射获取私有对象的技术,同时提到了SpringBoot中主数据源的配置方法。
摘要由CSDN通过智能技术生成

参考文章

http://blog.csdn.net/u012506661/article/details/53235725


分页插件  代码   主要是实现了interceptor  mybatis的拦截器

/**
 *自定义分页插件
 * 有2中方法可以实现
 * 1.通过拦截Executor.class这个类    这种方法其实比较耗
 * 2.通过拦截StatementHandler.class来实现拦截
 */
@Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}))
public class PageHelpInterceptor implements org.apache.ibatis.plugin.Interceptor {


    //默认使用MySQL   也可以通过springboot配置的时候注入
    public String dialect = "mysql";

    //主要是进行拦截
    public Object intercept(Invocation invocation) throws Throwable {
        //通过反射获取RoutingStatementHandler这个类
        RoutingStatementHandler routingStatementHandler = (RoutingStatementHandler) invocation.getTarget();
        //通过反射获取StatementHandler
        StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(routingStatementHandler, "delegate");
        //获取BoundSql对象里面有参数,sql等东西
        BoundSql boundSql = delegate.getBoundSql();
        Object object = boundSql.getParameterObject();
        if (object instanceof Page) {
            //分页设置
            Page<?> page = (Page<?>) object;
            String sql = boundSql.getSql();
            //处理sql语句
            String pageSql = getPageSql(sql, page);
            //这里处理获取总的记录数  需要的参数  这里相当于在执行sql语句之前  先进行统计总的记录数保存在page对象中
            MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(delegate, "mappedStatement");
            Connection connection = (Connection) invocation.getArgs()[0];

            //获取总的记录数
            setTotal(page, mappedStatement, connection);
            ReflectUtil.setFieldValue(boundSql, "sql", pageSql);
        }
        return invocation.proceed();
    }

    private void setTotal(Page<?> page, MappedStatement mappedStatement, Connection connection) {
        BoundSql boundSql = mappedStatement.getBoundSql(page);
        String countSql = getCountSql(boundSql.getSql());
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        BoundSql bs = new BoundSql(mappedStatement.getConfiguration(), countSql, parameterMappings, page);
        ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, page, bs);
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        try {
            ps = connection.prepareStatement(countSql);
            parameterHandler.setParameters(ps);
            resultSet = ps.executeQuery();
            while (resultSet.next()) {
                page.setTotal(resultSet.getInt(1));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();

                }
                if (ps != null) {
                    ps.close();

                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    public String getCountSql(String sql) {

        String countSql = "select count(*) from (" + sql+" ) temp";
        return countSql;
    }

    //对sql语句进行重新编写
    private String getPageSql(String sql, Page<?> page) {
        StringBuilder sb = new StringBuilder(200);
        if (dialect.equalsIgnoreCase("mysql")) {
            sb.append(sql);
            sb.append(" limit " + (page.getPageNum() - 1) * page.getPageSize() + " , " + page.getPageSize());
        } else if (dialect.equalsIgnoreCase("oracle")) {
            sb.append("select * from ( select temp.*,rownum row_id from (");
            sb.append(sql);
            sb.append(" ) temp where rownum<=" + page.getPageSize() * page.getPageNum() + " )");
            sb.append(" where row_id>" + (page.getPageNum() - 1) * page.getPageSize());
        }
        return sb.toString();

    }

    //查询总的记录数

    //只对executor进行拦截,当目标类为executor是,才进行对对象进行分装
    public Object plugin(Object o) {
        if (o instanceof StatementHandler) {
            return Plugin.wrap(o, this);
        } else {
            return o;
        }

    }

    public void setProperties(Properties properties) {
            String d = properties.getProperty("dialect");
            if(d!=null){
                this.dialect = d;
            }
    }
}

反射器代码   主要通过反射器可以拿到私有的对象   这个主要参考了 网上其他博主的代码

public class ReflectUtil {
    /**
     * 利用反射获取指定对象的指定属性
     * @param obj 目标对象
     * @param fieldName 目标属性
     * @return 目标属性的值
     */
    public static Object getFieldValue(Object obj, String fieldName) {
        Object result = null;
        Field field = ReflectUtil.getField(obj, fieldName);
        if (field != null) {
            field.setAccessible(true);
            try {
                result = field.get(obj);
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 利用反射获取指定对象里面的指定属性
     * @param obj 目标对象
     * @param fieldName 目标属性
     * @return 目标字段
     */
    private static Field getField(Object obj, String fieldName) {
        Field field = null;
        for (Class<?> clazz=obj.getClass(); clazz != Object.class; clazz=clazz.getSuperclass()) {
            try {
                field = clazz.getDeclaredField(fieldName);
                break;
            } catch (NoSuchFieldException e) {
                //这里不用做处理,子类没有该字段可能对应的父类有,都没有就返回null。
            }
        }
        return field;
    }

    /**
     * 利用反射设置指定对象的指定属性为指定的值
     * @param obj 目标对象
     * @param fieldName 目标属性
     * @param fieldValue 目标值
     */
    public static void setFieldValue(Object obj, String fieldName,
                                     String fieldValue) {
        Field field = ReflectUtil.getField(obj, fieldName);
        if (field != null) {
            try {
                field.setAccessible(true);
                field.set(obj, fieldValue);
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

springboot里面的配置文件   这个配置文件是 主数据源的配置文件

@Configuration
@MapperScan(basePackages = "com.quipoo.mybatis.primaryMapper",sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class PrimaryDataSourceConfig {

    @Bean(name = "primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    @Primary
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "primarySqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mybatis1/*.xml"));
        Properties properties = new Properties();
        properties.setProperty("dialect","mysql");
        PageHelpInterceptor pageHelpInterceptor = new PageHelpInterceptor();
        pageHelpInterceptor.setProperties(properties);
        bean.setPlugins(new Interceptor[]{pageHelpInterceptor});
        return bean.getObject();
    }

    @Bean(name = "primaryTransactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "primarySqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

# Spring Boot 集成 MyBatis, 分页插件 PageHelper, 通用 Mapper ## 项目依赖 ```xml <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <!--mapper--> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <!--pagehelper--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> ``` ## Spring DevTools 配置 在使用 DevTools 时,通用Mapper经常会出现 class x.x.A cannot be cast to x.x.A。 同一个类如果使用了不同的类加载器,就会产生这样的错误,所以解决方案就是让通用Mapper和实体类使用相同的类加载器即可。 DevTools 默认会对 IDE 中引入的所有项目使用 restart 类加载器,对于引入的 jar 包使用 base 类加载器,因此只要保证通用Mapper的jar包使用 restart 类加载器即可。 在 `src/main/resources` 中创建 META-INF 目录,在此目录下添加 spring-devtools.properties 配置,内容如下: ```properties restart.include.mapper=/mapper-[\\w-\\.]+jar restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar ``` 使用这个配置后,就会使用 restart 类加载加载 include 进去的 jar 包。 ## 集成 MyBatis Generator 通过 Maven 插件集成的,所以运行插件使用下面的命令: >mvn mybatis-generator:generate Mybatis Geneator 详解: >http://blog.csdn.net/isea533/article/details/42102297 ## application.properties 配置 ```properties #mybatis mybatis.type-aliases-package=tk.mybatis.springboot.model mybatis.mapper-locations=classpath:mapper/*.xml #mapper #mappers 多个接口时逗号隔开 mapper.mappers=tk.mybatis.springboot.util.MyMapper mapper.not-empty=false mapper.identity=MYSQL #pagehelper pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql ``` ## application.yml 配置 完整配置可以参考 [src/main/resources/application-old.yml](https://github.com/abel533/MyBatis-Spring-Boot/blob/master/src/main/resources/application-old.yml) ,和 MyBatis 相关的部分配置如下: ```yaml mybatis: type-aliases-package: tk.mybatis.springboot.model mapper-locations: classpath:mapper/*.xml mapper: mappers: - tk.mybatis.springboot.util.MyMapper not-empty: false identity: MYSQL pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true params: count=countSql ``` 注意 mapper 配置,因为参数名固定,所以接收参数使用的对象,按照 Spring Boot 配置规则,大写字母都变了带横线的小写字母。针对如 IDENTITY(对应i-d-e-n-t-i-t-y)提供了全小写的 identity 配置,如果 IDE 能自动提示,看自动提示即可。 ## SSM集成的基础项目 >https://github.com/abel533/Mybatis-Spring ## MyBatis工具 http://www.mybatis.tk - 推荐使用 Mybatis 通用 Mapper3 https://github.com/abel533/Mapper - 推荐使用 Mybatis 分页插件 PageHelper https://github.com/pagehelper/Mybatis-PageHelper ## 作者信息 - 作者博客:http://blog.csdn.net/isea533 - 作者邮箱:abel533@gmail.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值