Mybatis Plus入门进阶:特殊符号、动态条件、公共语句、关联查询、多租户插件

前言

Mybatis Plus入门进阶:特殊符号、动态条件、公共语句、关联查询、多租户插件
隐藏问题:批量插入saveBatch

文章目录

    • 前言
      • 注意点
      • 动态条件
      • xml公共语句
      • 关联查询
      • 动态表名
      • 使用自定义函数
      • 主键生成策略
      • saveBatch
      • 插件:多租户TenantLineInnerInterceptor

注意点

  • mapper.xml中大于、小于需要使用特殊符号

    <     <    小于号
    >     >    大于号
    &    &    和
    '   '    单引号
    "   "    双引号
    <=    <=   小于等于
    >=    >=   大于等于
    
  • 如果需要拼接
    字符串,可以使用 CDATA 包裹起来,让解析器将其视为文本而非标签

    <sql id="exampleSql">
      ', column4) AS combinedColumn
        FROM 
          your_table
      ]]>
    sql>
    

动态条件

  1. 使用if对参数值进行判断,非空才查询

    <if test="roleName != null and roleName != ''">
    	AND r.role_name like concat('%', #{roleName}, '%')
    if>
    
    • 参考
  2. 多个条件判断

    • 使用多个if

      <if test = "">if>
      <if test = "">if>
      
    • 使用when/otherwise

      <choose>
      	<when test="status == 2">
      		create_time DESC
      	when>
      	<otherwise>
      		create_time
      	otherwise>
      choose>
      

xml公共语句

  1. 定义

    <sql id="xxx">
       select a from b
    sql>
    
  2. 使用

    <select id = "yyy">
    	<include refId="xxx">include>
    	where name = 'mango'
    select>
    

关联查询

  1. 一对一

    • 正常的查询sql,定义返回的结果类型:resultMap

      <select id="selectRoleAll" resultMap="SysRoleResult">
      	select * from A left join B ...
      select>
      
      <resultMap type="SysRole" id="SysRoleResult">
      	<id     property="roleId"             column="role_id"     />
      	<result property="roleName"           column="role_name"   />
      resultMap>
      
  2. 一对多

    • A表与B表关联查询,其中A表与B表为一对多的关系,则查询结果使用

      <resultMap id = "xxx" type="com.xxxx">
      	<id column="id" property="id" />
          <collection property="yyy" ofType=zzz>
          	<result property="no" column="no"/>
          collection>
      resultMap>
      
    • 列名重复问题==> 使用别名

    • 分页存在问题(不建议分页时使用)==> 使用select

相关参考文章:

  • Mybatis Plus内置的分页查询

  • collection分页问题总结

  • collection查询一对多分页数据的Bug

  • collection分页问题

动态表名

当我们想要传的参数是表格的名称或是列名的时候,#{}这种方式就不生效了,需要使用${}

使用自定义函数

在xml中,使用了数据库自定义的函数,则需要带上模式名,或者在当前的模式下创建函数

自定义的函数(达梦数据库),默认是在sysdba下

主键生成策略

@TableId注解定义了主键生成的类型,具体查看枚举类IdType.java

  • AUTO

    • 数据库 ID自增,这种情况下将表中主键设置为自增,否则,没有设置主动设置id值进行插入时会报错
  • NONE

    • 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里默认 ASSIGN_ID),注意这里官网文档有误
  • INPUT

    • insert 前自行 set 主键值,在采用IKeyGenerator类型的ID生成器时必须为INPUT
  • ASSIGN_ID

    • 分配ID (主键类型为number或string),默认实现为雪花算法
  • ASSIGN_UUID

    • 分配 UUID

详细参考

saveBatch

  1. 特性及问题

    • 拼接sql:如果集合中的某个实体和它的上/下一个不一样,就不会拼接到insert中,而是会单独执行插入语句,所以多个实体不一样(某个字段为null),会拼出多个插入语句

    • 事务:事务回滚,如果在某一个拼接语句中,存在一条数据报错,那么整批会报错,如果上一批语句已经执行过了,则事务不会回滚,已经成功的仍旧是成功

  2. 解决方案:

    • 使用其他的批量插入:this.baseMapper.insertBatchSomeColumn(list);

      • 存在问题:数据库字段默认值不生效,需要手动对对象设值,或者对实体字段设值默认,如果为雪花算法,可使用IdWorker
    • 自定义批量插入

    • 设置插入字段策略

      • 局部字段忽略控制:@TableField(fill = FieldFill.INSERT,insertStrategy = FieldStrategy.IGNORED)

      • 全局

        mybatis-plus:
        	global-config:
        		db-config:
        			insert-strategy: ignored
        
      • 参考

插件:多租户TenantLineInnerInterceptor

处理逻辑类:BaseMultiTableInnerInterceptor

  • 忽略某个方法,需要重写TenantLineInnerInterceptor中的beforeQuery

相关文章参考

引入及使用租户

忽略多租户隔离自定义注解(未验证)

  1. 新增租户配置信息

    # 租户配置信息
    tenant:
      # 是否开启租户模式
      enable: true
      # 需要排除的多租户的表
      exclusionTable: sys_config,sys_dict_data
      # 租户字段名称
      column: tenant_id
    
  2. 对应增加配置类TenantProperties

    @Configuration
    @Getter
    public class TenantProperties {
    
        /**
         * 是否开启租户模式
         */
        @Value("${tenant.enable}")
        private Boolean enable;
    
        /**
         * 多租户字段名称
         */
        @Value("${tenant.column}")
        private String column;
    
        /**
         * 需要排除的多租户的表
         */
        @Value("${tenant.exclusionTable}")
        private List<String> exclusionTable;
    }
    
  3. 注入重载的租户配置

    @Configuration
    @RequiredArgsConstructor(onConstructor_ = @Autowired)
    @AutoConfigureBefore(MyBatisPlusConfig.class)
    public class TenantConfig {
    
        private final TenantProperties tenantProperties;
    
        @Bean
        public TenantLineInnerInterceptor tenantLineInnerInterceptor() {
            return new TenantLineInnerInterceptor(new TenantLineHandler() {
    
                @Override
                public Expression getTenantId() {
                    try {
                        String tenantId = SecurityUtils.getLoginUser().getTenantId();
                        if (tenantId != null) {
                            return new StringValue(tenantId);
                        }
                    } catch (ServiceException e) {
                        e.printStackTrace();
                    }
    
                    return new NullValue();
                }
    
                @Override
                public String getTenantIdColumn() {
                    return tenantProperties.getColumn();
                }
    
                @Override
                public boolean ignoreTable(String tableName) {
                    return tenantProperties.getExclusionTable().stream().anyMatch(
                            (t) -> t.equalsIgnoreCase(tableName)
                    );
                }
    
                @Override
                public boolean ignoreInsert(List columns, String tenantIdColumn) {
                    return TenantLineHandler.super.ignoreInsert(columns, tenantIdColumn);
                }
            });
        }
    }
    
  4. Mybatis Plus配置增加租户配置

    @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            // 多租户插件
            if (tenantProperties.getEnable()) {
                interceptor.addInnerInterceptor(tenantLineInnerInterceptor);
            }
            return interceptor;
        }
    

你可能感兴趣的:(后端,mybatis,数据库,租户插件)