【新增】新增 @TenantIgnore 注解,标记指定方法,忽略多租户的自动过滤,适合实现跨租户的逻辑

This commit is contained in:
YunaiV 2022-02-22 19:53:40 +08:00
parent 2598c033a9
commit 4d53944771
20 changed files with 195 additions and 215 deletions

View File

@ -0,0 +1,106 @@
package cn.iocoder.yudao.framework.tenant.config;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect;
import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJobHandlerDecorator;
import cn.iocoder.yudao.framework.tenant.core.mq.TenantRedisMessageInterceptor;
import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter;
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
import cn.iocoder.yudao.framework.tenant.core.web.TenantContextWebFilter;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true) // 允许使用 yudao.tenant.enable=false 禁用多租户
@EnableConfigurationProperties(TenantProperties.class)
public class YudaoTenantAutoConfiguration {
// ========== AOP ==========
@Bean
public TenantIgnoreAspect tenantIgnoreAspect() {
return new TenantIgnoreAspect();
}
// ========== DB ==========
@Bean
public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties properties,
MybatisPlusInterceptor interceptor) {
TenantLineInnerInterceptor inner = new TenantLineInnerInterceptor(new TenantDatabaseInterceptor(properties));
// 添加到 interceptor
// 需要加在首个主要是为了在分页插件前面这个是 MyBatis Plus 的规定
MyBatisUtils.addInterceptor(interceptor, inner, 0);
return inner;
}
// ========== WEB ==========
@Bean
public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter() {
FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new TenantContextWebFilter());
registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER);
return registrationBean;
}
// ========== Security ==========
@Bean
public FilterRegistrationBean<TenantSecurityWebFilter> tenantSecurityWebFilter(TenantProperties tenantProperties,
WebProperties webProperties,
GlobalExceptionHandler globalExceptionHandler,
TenantFrameworkService tenantFrameworkService) {
FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties,
globalExceptionHandler, tenantFrameworkService));
registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER);
return registrationBean;
}
// ========== MQ ==========
@Bean
public TenantRedisMessageInterceptor tenantRedisMessageInterceptor() {
return new TenantRedisMessageInterceptor();
}
// ========== Job ==========
@Bean
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public BeanPostProcessor jobHandlerBeanPostProcessor(TenantFrameworkService tenantFrameworkService) {
return new BeanPostProcessor() {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof JobHandler)) {
return bean;
}
// TenantJob 注解的情况下才会进行处理
if (!AnnotationUtil.hasAnnotation(bean.getClass(), TenantJob.class)) {
return bean;
}
// 使用 TenantJobHandlerDecorator 装饰
return new TenantJobHandlerDecorator(tenantFrameworkService, (JobHandler) bean);
}
};
}
}

View File

@ -1,33 +0,0 @@
package cn.iocoder.yudao.framework.tenant.config;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 多租户针对 DB 的自动配置
*
* @author 芋道源码
*/
@Configuration
// 允许使用 yudao.tenant.enable=false 禁用多租户
@ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true)
@EnableConfigurationProperties(TenantProperties.class)
public class YudaoTenantDatabaseAutoConfiguration {
@Bean
public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties properties,
MybatisPlusInterceptor interceptor) {
TenantLineInnerInterceptor inner = new TenantLineInnerInterceptor(new TenantDatabaseInterceptor(properties));
// 添加到 interceptor
// 需要加在首个主要是为了在分页插件前面这个是 MyBatis Plus 的规定
MyBatisUtils.addInterceptor(interceptor, inner, 0);
return inner;
}
}

View File

@ -1,46 +0,0 @@
package cn.iocoder.yudao.framework.tenant.config;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJobHandlerDecorator;
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 多租户针对 Job 的自动配置
*
* @author 芋道源码
*/
@Configuration
// 允许使用 yudao.tenant.enable=false 禁用多租户
@ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true)
public class YudaoTenantJobAutoConfiguration {
@Bean
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public BeanPostProcessor jobHandlerBeanPostProcessor(TenantFrameworkService tenantFrameworkService) {
return new BeanPostProcessor() {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof JobHandler)) {
return bean;
}
// TenantJob 注解的情况下才会进行处理
if (!AnnotationUtil.hasAnnotation(bean.getClass(), TenantJob.class)) {
return bean;
}
// 使用 TenantJobHandlerDecorator 装饰
return new TenantJobHandlerDecorator(tenantFrameworkService, (JobHandler) bean);
}
};
}
}

View File

@ -1,23 +0,0 @@
package cn.iocoder.yudao.framework.tenant.config;
import cn.iocoder.yudao.framework.tenant.core.mq.TenantRedisMessageInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 多租户针对 MQ 的自动配置
*
* @author 芋道源码
*/
@Configuration
// 允许使用 yudao.tenant.enable=false 禁用多租户
@ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true)
public class YudaoTenantMQAutoConfiguration {
@Bean
public TenantRedisMessageInterceptor tenantRedisMessageInterceptor() {
return new TenantRedisMessageInterceptor();
}
}

View File

@ -1,37 +0,0 @@
package cn.iocoder.yudao.framework.tenant.config;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter;
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 多租户针对 Web 的自动配置
*
* @author 芋道源码
*/
@Configuration
// 允许使用 yudao.tenant.enable=false 禁用多租户
@ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true)
@EnableConfigurationProperties(TenantProperties.class)
public class YudaoTenantSecurityAutoConfiguration {
@Bean
public FilterRegistrationBean<TenantSecurityWebFilter> tenantSecurityWebFilter(TenantProperties tenantProperties,
WebProperties webProperties,
GlobalExceptionHandler globalExceptionHandler,
TenantFrameworkService tenantFrameworkService) {
FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties,
globalExceptionHandler, tenantFrameworkService));
registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER);
return registrationBean;
}
}

View File

@ -1,28 +0,0 @@
package cn.iocoder.yudao.framework.tenant.config;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.tenant.core.web.TenantContextWebFilter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 多租户针对 Web 的自动配置
*
* @author 芋道源码
*/
@Configuration
// 允许使用 yudao.tenant.enable=false 禁用多租户
@ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true)
public class YudaoTenantWebAutoConfiguration {
@Bean
public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter() {
FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new TenantContextWebFilter());
registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER);
return registrationBean;
}
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.framework.tenant.core.aop;
import java.lang.annotation.*;
/**
* 忽略租户标记指定方法不进行租户的自动过滤
*
* 注意只有 DB 的场景会过滤其它场景暂时不过滤
* 1Redis 场景因为是基于 Key 实现多租户的能力所以忽略没有意义不像 DB 是一个 column 实现的
* 2MQ 场景有点难以抉择目前可以通过 Consumer 手动在消费的方法上添加 @TenantIgnore 进行忽略
*
* @author 芋道源码
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface TenantIgnore {
}

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.framework.tenant.core.aop;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
/**
* 忽略多租户的 Aspect基于 {@link TenantIgnore} 注解实现用于一些全局的逻辑
* 例如说一个定时任务读取所有数据进行处理
* 又例如说读取所有数据进行缓存
*
* @author 芋道源码
*/
@Aspect
@Slf4j
public class TenantIgnoreAspect {
@Around("@annotation(tenantIgnore)")
public Object around(ProceedingJoinPoint joinPoint, TenantIgnore tenantIgnore) throws Throwable {
Boolean oldIgnore = TenantContextHolder.isIgnore();
try {
TenantContextHolder.setIgnore(true);
// 执行逻辑
return joinPoint.proceed();
} finally {
TenantContextHolder.setIgnore(oldIgnore);
}
}
}

View File

@ -9,8 +9,16 @@ import com.alibaba.ttl.TransmittableThreadLocal;
*/
public class TenantContextHolder {
/**
* 当前租户编号
*/
private static final ThreadLocal<Long> TENANT_ID = new TransmittableThreadLocal<>();
/**
* 是否忽略租户
*/
private static final ThreadLocal<Boolean> IGNORE = new TransmittableThreadLocal<>();
/**
* 获得租户编号
*
@ -37,8 +45,22 @@ public class TenantContextHolder {
TENANT_ID.set(tenantId);
}
public static void setIgnore(Boolean ignore) {
IGNORE.set(ignore);
}
/**
* 当前是否忽略租户
*
* @return 是否忽略
*/
public static boolean isIgnore() {
return Boolean.TRUE.equals(IGNORE.get());
}
public static void clear() {
TENANT_ID.remove();
IGNORE.remove();
}
}

View File

@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import lombok.AllArgsConstructor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.LongValue;
/**
* 基于 MyBatis Plus 多租户的功能实现 DB 层面的多租户的功能
@ -20,12 +20,13 @@ public class TenantDatabaseInterceptor implements TenantLineHandler {
@Override
public Expression getTenantId() {
return new StringValue(TenantContextHolder.getRequiredTenantId().toString());
return new LongValue( TenantContextHolder.getRequiredTenantId());
}
@Override
public boolean ignoreTable(String tableName) {
return CollUtil.contains(properties.getIgnoreTables(), tableName);
return TenantContextHolder.isIgnore() // 情况一全局忽略多租户
|| CollUtil.contains(properties.getIgnoreTables(), tableName); // 情况二忽略多租户的表
}
}

View File

@ -1,14 +0,0 @@
package cn.iocoder.yudao.framework.tenant.core.job;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker;
/**
* 多租户 JobHandlerInvoker 拓展实现类
*
* @author 芋道源码
*/
public class TenantJobHandlerInvoker extends JobHandlerInvoker {
}

View File

@ -12,17 +12,23 @@ public class TenantUtils {
/**
* 使用指定租户执行对应的逻辑
*
* 注意如果当前是忽略租户的情况下会被强制设置成不忽略租户
* 当然执行完成后还是会恢复回去
*
* @param tenantId 租户编号
* @param runnable 逻辑
*/
public static void execute(Long tenantId, Runnable runnable) {
Long oldTenantId = TenantContextHolder.getTenantId();
Boolean oldIgnore = TenantContextHolder.isIgnore();
try {
TenantContextHolder.setTenantId(tenantId);
TenantContextHolder.setIgnore(false);
// 执行逻辑
runnable.run();
} finally {
TenantContextHolder.setTenantId(oldTenantId);
TenantContextHolder.setIgnore(oldIgnore);
}
}

View File

@ -1,6 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.yudao.framework.tenant.config.YudaoTenantDatabaseAutoConfiguration,\
cn.iocoder.yudao.framework.tenant.config.YudaoTenantWebAutoConfiguration,\
cn.iocoder.yudao.framework.tenant.config.YudaoTenantJobAutoConfiguration,\
cn.iocoder.yudao.framework.tenant.config.YudaoTenantMQAutoConfiguration,\
cn.iocoder.yudao.framework.tenant.config.YudaoTenantSecurityAutoConfiguration
cn.iocoder.yudao.framework.tenant.config.YudaoTenantAutoConfiguration

View File

@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import org.apache.ibatis.annotations.Mapper;
/**
@ -31,12 +30,10 @@ public interface FileMapper extends BaseMapperX<FileDO> {
/**
* 基于 Path 获取文件
* 实际上是基于 ID 查询
* 由于前端使用 <img /> 的方式获取图片所以需要忽略租户的查询
*
* @param path 路径
* @return 文件
*/
@InterceptorIgnore(tenantLine = "true")
default FileDO selectByPath(String path) {
return selectById(path);
}

View File

@ -1,12 +1,11 @@
package cn.iocoder.yudao.module.pay.dal.mysql.merchant;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelExportReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelPageReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@ -23,7 +22,6 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> {
}
@Select("SELECT id FROM pay_channel WHERE update_time > #{maxUpdateTime} LIMIT 1")
@InterceptorIgnore(tenantLine = "true") // 该方法忽略多租户原因该方法被异步 task 调用此时获取不到租户编号
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
default PageResult<PayChannelDO> selectPage(PayChannelPageReqVO reqVO) {

View File

@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@ -30,12 +29,6 @@ public interface DeptMapper extends BaseMapperX<DeptDO> {
}
@Select("SELECT id FROM system_dept WHERE update_time > #{maxUpdateTime} LIMIT 1")
@InterceptorIgnore(tenantLine = "true") // 该方法忽略多租户原因该方法被异步 task 调用此时获取不到租户编号
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
// TODO 芋艿后续想想有没可能优化下大体思路是支持某个方法忽略租户
@Select("SELECT * FROM system_dept")
@InterceptorIgnore(tenantLine = "true")
List<DeptDO> selectListIgnoreTenant();
}

View File

@ -1,11 +1,10 @@
package cn.iocoder.yudao.module.system.dal.mysql.permission;
import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
@ -29,7 +28,6 @@ public interface MenuMapper extends BaseMapperX<MenuDO> {
.eqIfPresent(MenuDO::getStatus, reqVO.getStatus()));
}
@InterceptorIgnore(tenantLine = "true") // 该方法忽略多租户原因该方法被异步 task 调用此时获取不到租户编号
default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
return selectOne(new LambdaQueryWrapper<MenuDO>().select(MenuDO::getId)
.gt(MenuDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null;

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.system.dal.mysql.permission;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@ -44,7 +43,6 @@ public interface RoleMenuMapper extends BaseMapperX<RoleMenuDO> {
}
@Select("SELECT id FROM system_role_menu WHERE update_time > #{maxUpdateTime} LIMIT 1")
@InterceptorIgnore(tenantLine = "true") // 该方法忽略多租户原因该方法被异步 task 调用此时获取不到租户编号
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
}

View File

@ -1,11 +1,10 @@
package cn.iocoder.yudao.module.system.dal.mysql.sms;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@ -23,7 +22,6 @@ public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> {
}
@Select("SELECT id FROM system_sms_channel WHERE update_time > #{maxUpdateTime} LIMIT 1")
@InterceptorIgnore(tenantLine = "true") // 该方法忽略多租户原因该方法被异步 task 调用此时获取不到租户编号
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
}

View File

@ -1,12 +1,11 @@
package cn.iocoder.yudao.module.system.dal.mysql.sms;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@ -17,7 +16,6 @@ import java.util.List;
public interface SmsTemplateMapper extends BaseMapperX<SmsTemplateDO> {
@Select("SELECT id FROM system_sms_template WHERE update_time > #{maxUpdateTime} LIMIT 1")
@InterceptorIgnore(tenantLine = "true") // 该方法忽略多租户原因该方法被异步 task 调用此时获取不到租户编号
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
default SmsTemplateDO selectByCode(String code) {