Mybatis Plus 求和插件
根据业务需求,需要自动根据业务的 amount 字段求和,实现原理同分页插件
@Data
@EqualsAndHashCode(callSuper = true)
public class SumAmountPage<T> extends Page<T> {
private Double sumAmount;
}
@Slf4j
public class SumAmountInnerInterceptor implements InnerInterceptor {
@Override
public boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
IPage<?> page = ParameterUtils.findPage(parameter).orElse(null);
if (page == null || page.getSize() < 0 || !page.searchCount() || !(page instanceof SumAmountPage)) {
return true;
}
SumAmountPage<?> sumAmountPage = (SumAmountPage<?>) page;
MappedStatement mappedStatement = buildMappedStatement(ms);
String sumAmountSqlStr = autoSumAmountSql(boundSql.getSql());
PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
BoundSql sumAmountSql = new BoundSql(mappedStatement.getConfiguration(), sumAmountSqlStr, mpBoundSql.parameterMappings(), parameter);
PluginUtils.setAdditionalParameter(sumAmountSql, mpBoundSql.additionalParameters());
CacheKey cacheKey = executor.createCacheKey(mappedStatement, parameter, rowBounds, sumAmountSql);
List<Object> result = executor.query(mappedStatement, parameter, rowBounds, resultHandler, cacheKey, sumAmountSql);
if (CollectionUtils.isNotEmpty(result) && Objects.nonNull(result.get(0))) {
sumAmountPage.setSumAmount((Double) result.get(0));
}
return true;
}
protected String autoSumAmountSql(String sql) {
try {
Select select = (Select) CCJSqlParserUtil.parse(sql);
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
SelectExpressionItem total = new SelectExpressionItem(new Column().withColumnName("sum(amount)")).withAlias(new Alias("sum"));
plainSelect.setSelectItems(Collections.singletonList(total));
return select.toString();
} catch (Exception e) {
log.error("自动生成统计金额sql失败 {}", sql, e);
}
return null;
}
protected MappedStatement buildMappedStatement(MappedStatement ms) {
String sumAmountId = ms.getId() + "_sumAmount";
Configuration configuration = ms.getConfiguration();
MappedStatement.Builder builder = new MappedStatement.Builder(configuration, sumAmountId, ms.getSqlSource(), ms.getSqlCommandType());
builder.resource(ms.getResource());
builder.fetchSize(ms.getFetchSize());
builder.statementType(ms.getStatementType());
builder.timeout(ms.getTimeout());
builder.parameterMap(ms.getParameterMap());
builder.resultMaps(Collections.singletonList(new ResultMap.Builder(configuration, Constants.MYBATIS_PLUS, Double.class, Collections.emptyList()).build()));
builder.resultSetType(ms.getResultSetType());
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return builder.build();
}
}
/**
* @author shalongfei
*/
@EnableTransactionManagement
@Configuration
@MapperScan("")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 必须放到分页插件前面,因为分页插件会修改SQL
interceptor.addInnerInterceptor(new SumAmountInnerInterceptor());
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
使用方式也比较简单,如下所示
public SumAmountPage<Payment> query() {
return this.page(new SumAmountPage<>(), new LambdaQueryWrapper<>());
}