现象: 框架中的分页插件不自动的查询count值了; 找了对应的分页插件信息并没有什么变化,并且在有些服务中可以正常使用,有些服务中不能正常使用了,这就很让人费解
首先这个分页的插件是自定义,自动查询count 数量,前端传递不同参数,对应的控制当前页,和每页显示几条;分页插件只对数据库的查询操作进行拦截,后面我会发源码出来;
原因: 近期在各服务项目中改用了seata 来出来分布式事物问题
alibaba-seata和自定义的数据库分页插件PaginationInterceptor相互影响了,只要是开启了seate 注解对应的服务,都会导致分页的插件不能正常的分页.是因为我们在初始化seata 时对sqlSessionFactory 进行了代理修改了一些内容导致了分页插件不能正常使用;
结论:如果对sqlSessionFactory 进行了代理,就需要彻底的把自己用到的一些功能信息都加上,不然就会导致一些bug出现sqlSessionFactoryBean.setPlugins(new Interceptor[] { pageHelper });
下面是分页插件代码;
public class PaginationInterceptor extends BaseInterceptor { private static final long serialVersionUID = 1L; @Override public Object intercept(Invocation invocation) throws Throwable { if (ConverterUtil.isEmpty(DIALECT)) { setProperties(null); } final MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; // //拦截需要分页的SQL //// if (mappedStatement.getId().matches(_SQL_PATTERN)) { // if (StringUtils.indexOfIgnoreCase(mappedStatement.getId(), _SQL_PATTERN) != -1) { Object parameter = invocation.getArgs()[1]; BoundSql boundSql = mappedStatement.getBoundSql(parameter); Object parameterObject = boundSql.getParameterObject(); // 获取分页参数对象 Page<Object> page = null; if (parameterObject != null) { page = convertParameter(parameterObject, page); } // 如果设置了分页对象,则进行分页 if (page != null && page.getPageSize() != -1) { if (StringUtils.isBlank(boundSql.getSql())) { return null; } String originalSql = boundSql.getSql().trim(); // 若不是多表关联分页查询,进行分页处理,关联查询则跳过 if (StringUtils.indexOfIgnoreCase(mappedStatement.getId(), "subQuery") == -1) { // 得到总记录数 page.setCount(SQLHelper.getCount(originalSql, null, mappedStatement, parameterObject, boundSql, log)); // 分页查询 本地化对象 修改数据库注意修改实现 String pageSql = SQLHelper.generatePageSql(originalSql, page, DIALECT); // if (log.isDebugEnabled()) { // log.debug("PAGE SQL:" + StringUtils.replace(pageSql, "\n", "")); // } invocation.getArgs()[2] = new RowBounds(RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT); BoundSql newBoundSql = new BoundSql(mappedStatement.getConfiguration(), pageSql, boundSql.getParameterMappings(), boundSql.getParameterObject()); //解决MyBatis 分页foreach 参数失效 start if (Reflections.getFieldValue(boundSql, "metaParameters") != null) { MetaObject mo = (MetaObject) Reflections.getFieldValue(boundSql, "metaParameters"); Reflections.setFieldValue(newBoundSql, "metaParameters", mo); } if (Reflections.getFieldValue(boundSql, "additionalParameters") != null) { Map<String, Object> map = (Map<String, Object>) Reflections.getFieldValue(boundSql, "additionalParameters"); Reflections.setFieldValue(newBoundSql, "additionalParameters", map); } //解决MyBatis 分页foreach 参数失效 end MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql)); invocation.getArgs()[0] = newMs; } else { String sqlName = mappedStatement.getId(); // 一对多翻页查询对应两个方法*SubQuery和*SubQueryCount count应只查询主表的记录 SubQuery应关联子表数据 final MappedStatement mappedStatementForCount = mappedStatement.getConfiguration().getMappedStatement(sqlName + "Count"); BoundSql boundSqlCount = mappedStatementForCount.getBoundSql(parameter); Object parameterObjectCount = boundSqlCount.getParameterObject(); if (StringUtils.isBlank(boundSqlCount.getSql())) { return null; } String originalSqlCount = boundSqlCount.getSql().trim(); page.setCount(SQLHelper.getCount(originalSqlCount, null, mappedStatement, parameterObjectCount, boundSqlCount, log)); } } // } return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { super.initProperties(properties); } private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) { 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()); builder.resultMaps(ms.getResultMaps()); builder.cache(ms.getCache()); 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; } } }
seata 初始化的代码
public class DynamicDataSourceConfiguration { @Autowired private MultiDataSourceRegister register; @Autowired private DynamicDataSource dynamicDataSource; @Autowired private PaginationInterceptor pageHelper; @PostConstruct public void initDataSourceProxy() { Map<String, DataSource> dataSources = register.getDataSources(); Map<Object, Object> targetDataSources = Maps.newHashMap(); dataSources.forEach((e, d)->{ DataSourceProxy dataSourceProxy = new DataSourceProxy(d); dataSources.put(e, dataSourceProxy); targetDataSources.put(e, dataSourceProxy); }); if(dataSources.containsKey("master")){ dynamicDataSource.setDefaultTargetDataSource(dataSources.get("master")); }else{ AtomicReference<DataSource> defaultDataSource = new AtomicReference(); dataSources.forEach((e, d)->{ if(ConverterUtil.isEmpty(defaultDataSource.get())){ defaultDataSource.set(d); } }); dynamicDataSource.setDefaultTargetDataSource(defaultDataSource.get()); } dynamicDataSource.setTargetDataSources(targetDataSources); dynamicDataSource.afterPropertiesSet(); } @Bean public SqlSessionFactory sqlSessionFactory()throws Exception{ SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dynamicDataSource); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath*:/mappings/**/*.xml")); sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory()); sqlSessionFactoryBean.setTypeAliasesPackage("com.wisea.cloud.common"); sqlSessionFactoryBean.setTypeAliasesSuperType(BaseEntity.class); org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setMapUnderscoreToCamelCase(true); sqlSessionFactoryBean.setConfiguration(configuration); sqlSessionFactoryBean.setPlugins(new Interceptor[] { pageHelper }); return sqlSessionFactoryBean.getObject(); } }
将工程中分页的插件 注入进来,进行设置
原文:https://www.cnblogs.com/wshuo/p/14211573.html