参考文章
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); } }