1. 新增分页接口聚合查询注解支持
2. 优化 databus api 日志记录的字段缺失问题 3. 新增 eplat sso 页面登录校验 4. 用户、部门编辑新增 seata 事务支持 5. 新增 iwork 流程发起接口 6. 新增 eban 同步用户时的岗位处理逻辑 7. 新增无 skywalking 时的 traceId 支持
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
package com.zt.plat.framework.mybatis.config;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.zt.plat.framework.mybatis.core.handler.DefaultDBFieldHandler;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
|
||||
import com.baomidou.mybatisplus.extension.incrementer.*;
|
||||
@@ -11,6 +11,8 @@ import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
|
||||
import com.baomidou.mybatisplus.extension.parser.cache.JdkSerialCaffeineJsqlParseCache;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.zt.plat.framework.mybatis.core.handler.DefaultDBFieldHandler;
|
||||
import com.zt.plat.framework.mybatis.core.sum.PageSumTableFieldAnnotationHandler;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
@@ -25,29 +27,40 @@ import java.util.concurrent.TimeUnit;
|
||||
*
|
||||
* @author ZT
|
||||
*/
|
||||
@AutoConfiguration(before = MybatisPlusAutoConfiguration.class) // 目的:先于 MyBatis Plus 自动配置,避免 @MapperScan 可能扫描不到 Mapper 打印 warn 日志
|
||||
@AutoConfiguration(before = MybatisPlusAutoConfiguration.class) // 先于官方自动配置,避免 Mapper 未扫描完成
|
||||
@MapperScan(value = "${zt.info.base-package}", annotationClass = Mapper.class,
|
||||
lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
|
||||
lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅单测需要
|
||||
public class ZtMybatisAutoConfiguration {
|
||||
|
||||
static {
|
||||
// 动态 SQL 智能优化支持本地缓存加速解析,更完善的租户复杂 XML 动态 SQL 支持,静态注入缓存
|
||||
// 使用本地缓存加速 JsqlParser 解析,复杂动态 SQL 性能更稳定
|
||||
JsqlParserGlobal.setJsqlParseCache(new JdkSerialCaffeineJsqlParseCache(
|
||||
(cache) -> cache.maximumSize(1024)
|
||||
.expireAfterWrite(5, TimeUnit.SECONDS))
|
||||
);
|
||||
cache -> cache.maximumSize(1024).expireAfterWrite(5, TimeUnit.SECONDS)));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
|
||||
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
|
||||
return mybatisPlusInterceptor;
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MetaObjectHandler defaultMetaObjectHandler() {
|
||||
return new DefaultDBFieldHandler(); // 自动填充参数类
|
||||
return new DefaultDBFieldHandler(); // 统一的公共字段填充
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MybatisPlusPropertiesCustomizer pageSumAnnotationCustomizer() {
|
||||
// 通过官方扩展点为 @PageSum 字段自动注入 exist = false 的 TableField 注解
|
||||
return properties -> {
|
||||
var globalConfig = properties.getGlobalConfig();
|
||||
if (globalConfig == null) {
|
||||
return;
|
||||
}
|
||||
globalConfig.setAnnotationHandler(
|
||||
new PageSumTableFieldAnnotationHandler(globalConfig.getAnnotationHandler()));
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
package com.zt.plat.framework.mybatis.core.mapper;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.zt.plat.framework.common.pojo.PageParam;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.common.pojo.SortablePageParam;
|
||||
import com.zt.plat.framework.common.pojo.SortingField;
|
||||
import com.zt.plat.framework.mybatis.core.sum.PageSumSupport;
|
||||
import com.zt.plat.framework.mybatis.core.util.JdbcUtils;
|
||||
import com.zt.plat.framework.mybatis.core.util.MyBatisUtils;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
@@ -43,14 +50,18 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
|
||||
// 特殊:不分页,直接查询全部
|
||||
if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
|
||||
List<T> list = selectList(queryWrapper);
|
||||
return new PageResult<>(list, (long) list.size());
|
||||
PageResult<T> pageResult = new PageResult<>(list, (long) list.size());
|
||||
PageSumSupport.tryAttachSummary(this, queryWrapper, pageResult);
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
// MyBatis Plus 查询
|
||||
IPage<T> mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
|
||||
selectPage(mpPage, queryWrapper);
|
||||
// 转换返回
|
||||
return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
|
||||
PageResult<T> pageResult = new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
|
||||
PageSumSupport.tryAttachSummary(this, queryWrapper, pageResult);
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
default <D> PageResult<D> selectJoinPage(PageParam pageParam, Class<D> clazz, MPJLambdaWrapper<T> lambdaWrapper) {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.zt.plat.framework.mybatis.core.sum;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Metadata describing a field participating in page-level SUM aggregation.
|
||||
*/
|
||||
final class PageSumFieldMeta {
|
||||
|
||||
private final String propertyName;
|
||||
private final String columnExpression;
|
||||
private final String selectAlias;
|
||||
private final Class<?> fieldType;
|
||||
|
||||
PageSumFieldMeta(String propertyName, String columnExpression, String selectAlias, Class<?> fieldType) {
|
||||
this.propertyName = propertyName;
|
||||
this.columnExpression = columnExpression;
|
||||
this.selectAlias = selectAlias;
|
||||
this.fieldType = fieldType;
|
||||
}
|
||||
|
||||
static PageSumFieldMeta of(Field field, String columnExpression) {
|
||||
String property = field.getName();
|
||||
return new PageSumFieldMeta(property, columnExpression, property, field.getType());
|
||||
}
|
||||
|
||||
String getPropertyName() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
String getColumnExpression() {
|
||||
return columnExpression;
|
||||
}
|
||||
|
||||
String getSelectAlias() {
|
||||
return selectAlias;
|
||||
}
|
||||
|
||||
Class<?> getFieldType() {
|
||||
return fieldType;
|
||||
}
|
||||
|
||||
String buildSelectSegment() {
|
||||
return "SUM(" + columnExpression + ") AS " + selectAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(propertyName, columnExpression, selectAlias, fieldType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof PageSumFieldMeta other)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(propertyName, other.propertyName)
|
||||
&& Objects.equals(columnExpression, other.columnExpression)
|
||||
&& Objects.equals(selectAlias, other.selectAlias)
|
||||
&& Objects.equals(fieldType, other.fieldType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PageSumFieldMeta{" +
|
||||
"propertyName='" + propertyName + '\'' +
|
||||
", columnExpression='" + columnExpression + '\'' +
|
||||
", selectAlias='" + selectAlias + '\'' +
|
||||
", fieldType=" + fieldType +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
package com.zt.plat.framework.mybatis.core.sum;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.core.handlers.AnnotationHandler;
|
||||
import com.zt.plat.framework.common.annotation.PageSum;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 让 {@link PageSum#exist()} 能够自动生成 {@link TableField#exist()} = false 的能力,
|
||||
* 这样 DO 层无需重复编写 {@code @TableField(exist = false)}。
|
||||
*/
|
||||
public class PageSumTableFieldAnnotationHandler implements AnnotationHandler {
|
||||
|
||||
private static final AnnotationHandler DEFAULT_HANDLER = new AnnotationHandler() { };
|
||||
/** 预构建 @TableField(exist = false) 的属性集合,避免重复创建 Map 对象 */
|
||||
private static final Map<String, Object> TABLE_FIELD_EXIST_FALSE_ATTRIBUTES =
|
||||
Collections.singletonMap("exist", Boolean.FALSE);
|
||||
|
||||
private final AnnotationHandler delegate;
|
||||
|
||||
public PageSumTableFieldAnnotationHandler(AnnotationHandler delegate) {
|
||||
this.delegate = delegate != null ? delegate : DEFAULT_HANDLER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> T getAnnotation(Class<?> target, Class<T> annotationClass) {
|
||||
return delegate.getAnnotation(target, annotationClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> boolean isAnnotationPresent(Class<?> target, Class<T> annotationClass) {
|
||||
return delegate.isAnnotationPresent(target, annotationClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> T getAnnotation(java.lang.reflect.Method method, Class<T> annotationClass) {
|
||||
return delegate.getAnnotation(method, annotationClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> boolean isAnnotationPresent(java.lang.reflect.Method method, Class<T> annotationClass) {
|
||||
return delegate.isAnnotationPresent(method, annotationClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> T getAnnotation(Field field, Class<T> annotationClass) {
|
||||
T annotation = delegate.getAnnotation(field, annotationClass);
|
||||
if (annotation != null || annotationClass != TableField.class) {
|
||||
return annotation;
|
||||
}
|
||||
PageSum pageSum = delegate.getAnnotation(field, PageSum.class);
|
||||
if (pageSum != null && !pageSum.exist()) {
|
||||
// 当字段只用于分页汇总时,动态合成一个 exist = false 的 TableField 注解
|
||||
return annotationClass.cast(synthesizeTableField(field));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> boolean isAnnotationPresent(Field field, Class<T> annotationClass) {
|
||||
if (delegate.isAnnotationPresent(field, annotationClass)) {
|
||||
return true;
|
||||
}
|
||||
if (annotationClass != TableField.class) {
|
||||
return false;
|
||||
}
|
||||
PageSum pageSum = delegate.getAnnotation(field, PageSum.class);
|
||||
return pageSum != null && !pageSum.exist();
|
||||
}
|
||||
|
||||
private static TableField synthesizeTableField(Field field) {
|
||||
return AnnotationUtils.synthesizeAnnotation(TABLE_FIELD_EXIST_FALSE_ATTRIBUTES, TableField.class, field);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.zt.plat.framework.mybatis.core.sum;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.zt.plat.framework.common.annotation.PageSum;
|
||||
import com.zt.plat.framework.common.pojo.PageResult;
|
||||
import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
class PageSumSupportTest {
|
||||
|
||||
@Test
|
||||
void shouldAttachSummaryWhenAnnotationPresent() {
|
||||
TestMapper mapper = createMapperProxy();
|
||||
PageResult<TestEntity> pageResult = new PageResult<>(Collections.emptyList(), 0L);
|
||||
QueryWrapper<TestEntity> wrapper = new QueryWrapper<>();
|
||||
|
||||
PageSumSupport.tryAttachSummary(mapper, wrapper, pageResult);
|
||||
|
||||
assertFalse(pageResult.getSummary().isEmpty());
|
||||
assertEquals(new BigDecimal("123.45"), pageResult.getSummary().get("amount"));
|
||||
assertEquals(new BigDecimal("50"), pageResult.getSummary().get("virtualAmount"));
|
||||
}
|
||||
|
||||
private TestMapper createMapperProxy() {
|
||||
InvocationHandler handler = new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (method.getDeclaringClass() == Object.class) {
|
||||
return method.invoke(this, args);
|
||||
}
|
||||
if ("selectMaps".equals(method.getName())) {
|
||||
Map<String, Object> row = new HashMap<>();
|
||||
row.put("amount", new BigDecimal("123.45"));
|
||||
row.put("virtualAmount", new BigDecimal("50"));
|
||||
return List.of(row);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
};
|
||||
return (TestMapper) Proxy.newProxyInstance(
|
||||
TestMapper.class.getClassLoader(),
|
||||
new Class[]{TestMapper.class},
|
||||
handler);
|
||||
}
|
||||
|
||||
interface TestMapper extends BaseMapperX<TestEntity> {
|
||||
}
|
||||
|
||||
static class TestEntity {
|
||||
@PageSum(column = "amount")
|
||||
private BigDecimal amount;
|
||||
|
||||
@PageSum(column = "virtual_column", exist = false)
|
||||
private BigDecimal virtualAmount;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user