# 一.介绍

# 1.介绍说明

DynamicTableNameInnerInterceptor是 MyBatis 持久化框架中的一个拦截器,允许在运行时动态替换 SQL 语句中的表名。

使用该拦截器可以方便地实现在不同的数据库实例或不同的表结构之间进行切换,同时也可以通过该拦截器实现数据分表或数据分区等功能。

DynamicTableNameInnerInterceptor的主要作用是在 MyBatis 执行 SQL 语句时,动态地替换 SQL 语句中的表名。 具体来说,当使用该拦截器时,在 SQL 语句中可以使用${}占位符表示要替换的表名,同时需要配置一个动态表名解析器,根据当前的上下文环境(如请求参数、会话信息等)动态地生成要替换的表名。 当 MyBatis 执行 SQL 语句时,DynamicTableNameInnerInterceptor会拦截 SQL 语句并将占位符${}替换为实际的表名,然后将替换后的 SQL 语句交给下一个拦截器或执行器执行。 使用DynamicTableNameInnerInterceptor的主要优点是可以方便地实现在不同的数据库实例或不同的表结构之间进行切换,同时也可以通过该拦截器实现数据分表或数据分区等功能。

除了在 MyBatis 中动态替换表名外,DynamicTableNameInnerInterceptor还有一些其他的作用:

  1. 实现数据分表或数据分区 通过动态表名解析器,可以根据特定的规则生成动态表名,从而实现数据分表或数据分区。例如,可以根据用户 ID 对用户数据进行分表,或者根据时间对数据进行分区。
  2. 隐藏数据表名 在某些情况下,为了安全或其他目的,可能需要隐藏数据库的表名。使用DynamicTableNameInnerInterceptor可以将表名进行动态替换,从而达到隐藏表名的效果。
  3. 提高系统的可扩展性 使用DynamicTableNameInnerInterceptor可以将不同的数据表或数据库实例进行解耦,从而提高系统的可扩展性。例如,可以将一个大型的数据库系统分成多个小型的数据库实例,然后通过动态表名解析器将 SQL 语句分发到不同的实例中。
  4. 简化代码开发 通过使用DynamicTableNameInnerInterceptor,可以避免在代码中硬编码 SQL 语句中的表名,从而简化代码的开发和维护。在应对表结构频繁变化的场景下,使用该拦截器能够更快速地实现表名变更,从而降低维护成本。

总之,DynamicTableNameInnerInterceptor是一个非常有用的拦截器,在 MyBatis 的实际开发中具有广泛的应用场景。

# 二.使用

# 1.pom

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>
1
2
3
4
5

# 2.yaml

#动态获取表名
dynamic-table:
  ads_day_city_rep: _uat_0403
  ads_day_region_rep: _uat_0403
  ads_day_country_rep: _uat_0403
1
2
3
4
5

# 3.config

使用 HashMap 在多线程情况下是不安全的

@Configuration
@ConfigurationProperties(value = "dynamic-table")
public class DynamicTableProperties extends HashMap<String, String> {
}
1
2
3
4

# 4.MybatisPlusConfig

@Configuration
public class MybatisPlusConfig {

    @Autowired
    private DynamicTableProperties dynamicTableProperties;

    /**
     * 新版的插件配置
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> tableName + this.dynamicTableProperties.getOrDefault(tableName, ""));
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);

        // 分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        // 乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        // 防止全表更新与删除插件
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());

        return interceptor;
    }

    /**
     * 自动填充配置
     *
     * @return
     */
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new MetaObjectHandler() {
            @Override
            public void insertFill(MetaObject metaObject) {
                Date curDate = new Date();
                this.strictInsertFill(metaObject, "createdTime", Date.class, curDate);
                this.strictInsertFill(metaObject, "updatedTime", Date.class, curDate);
                this.strictInsertFill(metaObject, "createdBy", String.class, OAuthUser.getOrAnonymous().getSn());
                this.strictInsertFill(metaObject, "updatedBy", String.class, OAuthUser.getOrAnonymous().getSn());
            }

            @Override
            public void updateFill(MetaObject metaObject) {
                Date curDate = new Date();
                this.strictUpdateFill(metaObject, "updatedTime", Date.class, curDate);
                this.strictUpdateFill(metaObject, "updatedBy", String.class, OAuthUser.getOrAnonymous().getSn());
            }
        };
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
上次更新: 10/29/2024, 10:27:50 AM