热爱技术,追求卓越
不断求索,精益求精

【12】Mybatis-Plus配置,实现多租户、逻辑删除、乐观锁

从0开始搭建后台管理系统,这是No12。上一篇我们讲到了:增加Mybatis-Plus依赖。这一节,我们就来看看怎么配置Mybatis-Plus。

添加模块yuen-starter-mybatisplus

在yuen-framework模块下增加子模块yuen-starter-mybatisplus,引入mybatis-plus-spring-boot3-starter依赖,创建包cn.lovecto.yuen.framework.mybatisplus.confg。

创建类YuenMybatisplusAutoConfiguration,配置Mybatis-Plus多租户支持、分页支持、乐观锁支持

package cn.lovecto.yuen.framework.mybatisplus.confg;

import java.util.List;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.net.NetUtil;
import cn.lovecto.yuen.common.tenant.YuenTenantProperties;
import cn.lovecto.yuen.common.utils.TenantUtils;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NullValue;

/**
 * 配置多租户支持、分页支持、乐观锁支持
 * @ClassName: YuenMybatisplusAutoConfiguration
 * @Description: Mybatisplus配置类
 * @author Jun.Yang 24696026@qq.com
 * @date 2025年12月22日 上午10:40:18
 *
 */
@AutoConfiguration(before = MybatisPlusAutoConfiguration.class)
@EnableTransactionManagement(proxyTargetClass = true)
@MapperScan("${mybatis-plus.mapperPackage}")
@PropertySource(value = "classpath:common-mybatis.yml")
@EnableConfigurationProperties(YuenTenantProperties.class)
public class YuenMybatisplusAutoConfiguration {

	@Autowired
	private YuenTenantProperties tenantProperties;

	/**
	 * 配置 MyBatis-Plus 的核心拦截器 注意:这里返回的是 MybatisPlusInterceptor,会被 Dynamic Datasource
	 * 自动识别和包装
	 */
	@Bean
	public MybatisPlusInterceptor mybatisPlusInterceptor() {
		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

		// 1. 多租户插件
		interceptor.addInnerInterceptor(tenantLineInnerInterceptor());

		// 2. 分页插件 (放在多租户之后)
		interceptor.addInnerInterceptor(paginationInnerInterceptor());

		// 3. 乐观锁插件 (通常放在最后)
		interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());

		return interceptor;
	}

	/**
	 * 多租户
	 * 
	 * @return
	 */
	private TenantLineInnerInterceptor tenantLineInnerInterceptor() {
		return new TenantLineInnerInterceptor((new TenantLineHandler() {
			@Override
			public Expression getTenantId() {
				Integer tenant = TenantUtils.getTenant();
				if (tenant == null) {
					return new NullValue();
				}
				// 返回租户
				return new LongValue(TenantUtils.getTenant());
			}

			@Override
			public boolean ignoreTable(String tableName) {
				Integer tenant = TenantUtils.getTenant();
				if (tenant != null) {
					List<String> ignoreTables = tenantProperties.getIgnoreTables();
					if (!CollectionUtil.isEmpty(ignoreTables)) {
						return ignoreTables.contains(tableName);
					}
				}
				return true;
			}
		}));
	}

	/**
	 * 分页
	 * 
	 * @return
	 */
	private PaginationInnerInterceptor paginationInnerInterceptor() {
		PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        // 分页合理化
        paginationInnerInterceptor.setOverflow(true);
        return paginationInnerInterceptor;
	}

	/**
	 * 乐观锁
	 * 
	 * @return
	 */
	private OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
		return new OptimisticLockerInnerInterceptor();
	}

	/**
	 * 雪花ID生成器
	 */
	@Bean
	public IdentifierGenerator idGenerator() {
		// 使用网卡信息绑定雪花生成器,防止分布式集群的情况下,雪花ID重复
		return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
	}

}

MyBatisPlus通用配置

# 内置配置
# MyBatisPlus通用配置
# https://baomidou.com/config/
mybatis-plus:
  # 启动时是否检查 MyBatis XML 文件的存在,默认不检查
  checkConfigLocation: false
  configuration:
    # 自动驼峰命名规则(camel case)映射
    mapUnderscoreToCamelCase: true
    # MyBatis 自动映射策略
    # NONE:不启用 PARTIAL:只对非嵌套 resultMap 自动映射 FULL:对所有 resultMap 自动映射
    autoMappingBehavior: FULL
    # MyBatis 自动映射时未知列或未知属性处理策
    # NONE:不做处理 WARNING:打印相关警告 FAILING:抛出异常和详细信息
    autoMappingUnknownColumnBehavior: NONE
    # 更详细的日志输出 会有性能损耗 org.apache.ibatis.logging.stdout.StdOutImpl
    # 关闭日志记录 (可单纯使用 p6spy 分析) org.apache.ibatis.logging.nologging.NoLoggingImpl
    # 默认日志输出 org.apache.ibatis.logging.slf4j.Slf4jImpl
    logImpl: org.apache.ibatis.logging.nologging.NoLoggingImpl
  global-config:
    # 是否打印 Logo banner
    banner: true
    dbConfig:
      # 主键类型
      # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
      idType: ASSIGN_ID
      # 逻辑删除字段
      logicDeleteField: deleted
      # 逻辑已删除值
      logicDeleteValue: 1
      # 逻辑未删除值
      logicNotDeleteValue: 0
      insertStrategy: NOT_NULL
      updateStrategy: NOT_NULL
      whereStrategy: NOT_NULL

mybatis-plus应用配置

# mybatis-plus配置
mybatis-plus:
  # 多包名使用逗号隔开
  mapperPackage: cn.lovecto.yuen.**.mapper
  # 对应的 XML 文件位置
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # 实体扫描,多个逗哈隔开
  typeAliasesPackage: cn.lovecto.yuen.**.domain
  global-config:
    dbConfig:
      # 主键类型
      # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
      idType: ASSIGN_ID
赞(0)
未经允许不得转载:LoveCTO » 【12】Mybatis-Plus配置,实现多租户、逻辑删除、乐观锁

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

热爱技术 追求卓越 精益求精