mybatis
这里介绍一下 mybatis 的使用。
功能介绍
主要包含在 wmeimob-spring-boot-starter-mybatis
jar 中。
支持的功能:
- 基础 baseEntity
- 移除 druid ad filter
- 通用 json 类型处理器
- FastjsonListTypeHandler
- FastjsonTypeHandler
- JacksonTypeHandler
- JSONArrayTypeHandler
- JsonTypeHandler
- IntegerListHandler
- LongListHandler
- StringListHandler
- IntegerToBooleanHandler
- mapper 扩展
- mybatis.plus 抽象接口 BaseMapperExtend
- tk.mybatis 抽象接口 CrudMapper
mybatis-plus 高级特性
- 自动逻辑删
通过使用如下注解来实现:
java
@TableLogic(delval = "id", value = "0")
- 乐观锁
通过使用如下注解来实现:
java
@Version
- 多租户
通过实现TenantLineHandler
接口来自定义处理逻辑。下面是一个示例:
java
/**
* 租户数据隔离处理器
*
* @author mjyang
* @date 2023/9/15 10:58
*/
@AllArgsConstructor
public class TenantLineHandlerImpl implements TenantLineHandler {
private final List<String> includeTableNames;
private final String tenantIdColumn;
@Override
public Expression getTenantId() {
return new LongValue(TenantContextHolder.geId());
}
@Override
public String getTenantIdColumn() {
return tenantIdColumn;
}
@Override
public boolean ignoreTable(String tableName) {
return !includeTableNames.contains(tableName);
}
}
java
/**
* 租户上下文 holder
*
* @author mjyang
* @date 2023/9/15 11:03
*/
public class TenantContextHolder {
/**
* 当前租户信息
*/
private static final ThreadLocal<Long> TENANT_ID = new ThreadLocal<>();
/**
* 获得租户 id
*
* @return long
*/
public static Long get() {
return TENANT_ID.get();
}
/**
* 设置租户id
*
* @param id 租户 id
*/
public static void put(Long id) {
TENANT_ID.set(id);
}
public static void clear() {
TENANT_ID.remove();
}
}
java
/**
* 租户 filter
*
* @author mjyang
* @date 2023/9/15 11:01
*/
@Component
public class TenantTenantFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
TenantContextHolder.setId(xxx);
try {
chain.doFilter(request, response);
} finally {
TenantContextHolder.clear();
}
}
}
java
@Component
@EnableConfigurationProperties(TenantProperties.class)
public class MyBatisInterceptorPostProcessor implements BeanPostProcessor {
@Resource
private TenantProperties tenantProperties;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof MybatisPlusInterceptor) {
MybatisPlusInterceptor interceptor = (MybatisPlusInterceptor) bean;
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandlerImpl(
this.tenantProperties.getIncludeTableNames(),
this.tenantProperties.getTenantIdColumn()
)));
}
return bean;
}
}
java
/**
* 租户配置类
*
* @author mjyang
* @date 2023/9/15 14:30
*/
@ConfigurationProperties("mybatis-plus")
@Getter
@Setter
public class TenantProperties {
/**
* 要包含的表名
*/
private List<String> includeTableNames;
/**
* 租户字段
*/
private String tenantIdColumn;
}
这样处理后,业务逻辑处理时会自动加上租户字段。如果有些业务想忽略租户时,则可以使用注解@IgnoreTenant
。以下是注解实现代码:
java
/**
* 忽略租户拦截
*
* @author mjyang
* @date 2022/4/1 11:02
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IgnoreTenant {
}
java
/**
* 忽略租户条件拦截器
*
* @author mjyang
* @date 2022/4/1 11:01
*/
@Aspect
@Component
public class IgnoreTenantAspect {
@Pointcut("@annotation(IgnoreTenant)")
public void pointCut() {
}
@Around("pointCut()")
public Object myAround(ProceedingJoinPoint point) throws Throwable {
Class<?> targetClass = point.getTarget().getClass();
MethodSignature methodSignature = (MethodSignature) point.getSignature();
Method method = targetClass.getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes());
IgnoreTenant ignoreTenant = AnnotationUtil.getAnnotation(method, IgnoreTenant.class);
if (ignoreTenant == null) {
return point.proceed();
}
InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().tenantLine(true).build());
try {
return point.proceed();
} finally {
InterceptorIgnoreHelper.clearIgnoreStrategy();
}
}
}
tk.mybatis
- 自动逻辑删
通过使用如下注解来实现:
java
@LogicDelete
- 乐观锁
通过使用如下注解来实现:
java
@Version