—— 阿尔伯特·爱因斯坦

程序员の奇妙冒险

我开源的项目JavaMyBatisSpring Boot多租户
2025-05-23 10:33阅读:259评论:0

开源项目-多租户插件druid-multi-tenant-starter

druid-multi-tenant-starter 目标多租户插件,快速集成,开箱即用,支持单个租户以及多个租户,基于alibaba druid 解析SQL,开发过程中只需要像平时一样写SQL语句即可,执行SQL最终会被拦截串改,最终把租户字段添加到SQL语句中,生成新的SQL语句,此过程你无需关

_PROTECTED12_PROTECTED17_PROTECTED16_PROTECTED18_PROTECTED13_ - [x] mybatisinterceptor mybatis拦截器策略,需项目使用的是mybatis ORM框架, 如果项目使用mybatis ORM 框架,推荐使用此方式
  • jpa__PROTECTED_38__filter 过滤器策略,不管是哪种 ORM框架,只需要数据库连接使用的数据源是 DruidDataSource 即可
  • _PROTECTED14_PROTECTED19_PROTECTED0_PROTECTED20_PROTECTED1_PROTECTED21_PROTECTED2_PROTECTED22_PROTECTED3_PROTECTED23_PROTECTED4_PROTECTED24_PROTECTED5_PROTECTED25_PROTECTED6_PROTECTED26_PROTECTED7_PROTECTED27_PROTECTED8_PROTECTED28_PROTECTED9_PROTECTED29_PROTECTED10_PROTECTED30_PROTECTED15_PROTECTED31_PROTECTED11__项目中引入以下依赖
    1
    2
    3
    4
    5
    6
    <dependency>
    <groupId>io.github.osinn</groupId>
    <artifactId>druid-multi-tenant-starter</artifactId>
    <version></version>
    </dependency>
     
    _PROTECTED0__
    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
    -- 1.5.6 mybatis.tenant.config multi-tenant.config
    multi-tenant:
    config:
    # 是否启用多租户插件
    enable: true
    # 数据库表租户ID的列名
    tenant-id-column: tenant_id
     
    --
    multi-tenant:
    config:
    # 是否使用MyBatis拦截器方式修改sql
    enable: true
    # 数据库表租户ID的列名字段
    tenant-id-column: tenant_id
    # 数据库方言,可选,如果不指定会从事务数据元中自动识别获取方言类型
    db-type: mysql
    # SQL 拦截策略,默认 mybatis 拦截器,如果不是mybatis,且使用的是 DruidDataSource 数据源,推荐使用 druid_filter 过滤器策略
    # druid_filter 只支持使用 DruidDataSource 数据数据源连接数据库
    sql-interceptor-strategy: mybatis_interceptor
    # 是否启用切面方式忽略租户ID字段,默认不开启,开启后 @IgnoreTenantIdField 注解不仅仅可以使用在mybatis Mapper接口方法上,也可以使用在Service任意接口上
    enable-pointcut-advisor-ignore-tenant-id: false
    # 是否忽略表按租户ID过滤,默认所有表都按租户ID过滤,指定表名称(区分大小写全等判断)
    ignore-table-name:
    - user_role # 内部全等判断
    ignore-match-table-alias
    # 匹配判断指定表别名称是否忽略表按租户ID过滤(区分大小写匹配判断)
    - temp # 内部判断 以 temp 为前缀的别名进行忽略过滤
    # 根据表名前缀判断是否忽略表按租户ID过滤
    ignore-table-name-prefix:
    - act_ # 内部判断 以 act_ 为前缀的别名进行忽略过滤
    # 多数据源情况下指定忽略跳过的数据源名称(需要重写ITenantService接口中的ignoreDynamicDatasource方法自行提供获取当前执行的数据源名称)
    ignore-dynamic-datasource:
    - demoDataSource # 内部全等判断
    # 数据源包装类型, 默认是 null
    #项目中存在 baomidou(苞米豆) 动态数据源,需要指定 baomidou_dynamic_data_source
    #
    # 项目中使用 sleuth 代理 jdbc 同时使用baomidou(苞米豆) 动态数据源,需要指定 sleuth_baomidou_dynamic_data_source_wrapper ,否则需要禁用 sleuth 中的 jdbc 代理
    # 如果项目中使用到 sleuth 同时使用baomidou(苞米豆) 动态数据源,应该禁用 sleuth 中的 jdbc 代理,例如以下配置,否则 sql-interceptor-strategy: druid_filter 是不会添加druid过滤器多租户 SQL 解析
    # spring:
    # sleuth:
    # jdbc:
    # enabled: false
    data-source-wrapper-type: baomidou_dynamic_data_source
    # 是否自定义数据源,默认是 false,true时会调用addCustomDataSourceProxySqlParser()方法,用于自定义数据源添加SQL解析器
    enable-custom-data-source: false
     
    • 如果SQL中表名不在 ___PROTECTED_13__0___PROTECTED_14__7___PROTECTED_15__1___PROTECTED_16__8___PROTECTED_17__2___PROTECTED_18__9___PROTECTED_19__5___PROTECTED_20__10___PROTECTED_21__3___PROTECTED_22__11___PROTECTED_23__4___PROTECTED_24__12___PROTECTED_25__6__
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /**
    * ID
    *
    * @author wency_cai
    * @since 1.5.6
    */
    @Service
    public class TenantServiceImpl extends TenantApplicationContext {
     
    @Override
    public List<Object> getTenantIds() {
    Long tenantId = 1L;
    List<Object> tenantIdList = new ArrayList<>();
    tenantIdList.add(tenantId);
    return tenantIdList;
    }
     
    }
     
    _PROTECTED0__
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    /**
    * ID
    *
    * @author wency_cai
    *
    * @since 1.5.6 TenantApplicationContext ID
    */
    @Service
    public class TenantServiceImpl extends TenantApplicationContext {
     
    @Override
    public List<Object> getTenantIds() {
    // 查询系统多租户id,如果有多个返回多个值即可
    int tenantId = 1;
    return Lists.newArrayList(tenantId);
    }
    // 如果需要指定某个数据源跳过设置租户ID,可以重写此方法,并且在yml配置文件中配置 ignore-dynamic-datasource 指定忽略的数据源名称
    @Override
    public String ignoreDynamicDatasource() {
    // 过去当前执行的数据源名称, 空则需要执行解析设置租户ID
    return ;
    }
    // 如果开发者需要自行解析SQL,可以重新此方法,并返回新的SQL语句,返回值为空时则继续执行默认解析逻辑,有返回值则直接返回且不会执行默认的解析逻辑
    @Override
    public String customizeParser(String originalSQL, Object paramTenantId) {
    return null;
    }
     
    // 如果开发者想要在执行默认的解析逻辑前做点什么,可以重写此方法,如果有返回值则会覆盖原始SQL语句(originalSQL)
    @Override
    public String before(String originalSQL, Object paramTenantId) {
    System.out.println("执行默认解析逻辑前 执行了 before方法");
    return null;
    }
     
    // 如果开发者想要在执行默认的解析逻辑后做点什么,可以重写此方法,如果有返回值则会覆盖解析后的SQL语句(newSQL)
    @Override
    public String after(String newSQL, Object paramTenantId) {
    System.out.println("执行默认解析逻辑后 执行了 after方法");
    // return newSQL + " and tenant_id = 123456";
    return null;
    }
    /**
    * (线tenant_id)
    * init()sqltenant_id ThreadLocal
    * 线tenant_idtenant_idtrue
    *
    * @return true , false
    */
    @Override
    public boolean skipParser() {
    return false;
    }
    /**
    * yml enable-pointcut-advisor = true 使 ThreadLocal
    * : threadLocalSkipParserSet > skipParser ThreadLocal > threadLocalSkipParserClear
    * 使 ThreadLocal ThreadLocal set myThreadLocal.set(xxxx)
    * ThreadLocal
    * <p>
    * 使 ThreadLocal 线( 使@IgnoreTenantIdField ID)
    * 线()使 TransmittableThreadLocal 线 skipParserthreadLocalSkipParserSetthreadLocalSkipParserClear
    *
    * @since 1.5.6
    */
    @Override
    public void threadLocalSkipParserSet() {
    IGNORE_TENANT.set(Boolean.TRUE);
    }
     
    /**
    * yml enable-pointcut-advisor = true 使 ThreadLocal
    * 使 ThreadLocal ThreadLocal clear myThreadLocal.clear()
    * ThreadLocal
    *
    * @since 1.5.6
    */
    @Override
    public void threadLocalSkipParserClear() {
    IGNORE_TENANT.remove();
    }
    /**
    * bean sql
    * yml enable-custom-data-source = true
    *
    * @param dataSource
    * @param defaultSqlParser sql
    * @return sql dataSource , null
    * @since 1.5.6
    */
    default Object addCustomDataSourceProxySqlParser(Object dataSource, DefaultSqlParser defaultSqlParser) {
     
    return null;
    }
    }
     
    • 到此整合完成
    _PROTECTED0_ > 默认调用 ITenantService.getTenantIds() 接口方法获取租户ID - 此方式传入tenantId值只支持 mybatisinterceptor 拦截策略(mybatis 拦截器)
    1
    2
    3
    4
    5
    6
    7
    8
    public interface UserMapper {
     
    /**
    * IDListSet
    */
    User getUserInfoById(@Param("userId") Long userId, @Param("tenant_id") Long tenantId);
    }
     
    • @Param("tenant__PROTECTED_5__id <font color=#FF000 >___PROTECTED_6__2___PROTECTED_7__3___PROTECTED_8__0___PROTECTED_9__4___PROTECTED_10__1__
    • mybatis Mapper接口方法上使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface UserMapper {
     
    /**
    * @IgnoreTenantIdField
    */
    @IgnoreTenantIdField
    void deleteTestIgnoreTenantIdById(Long id);
    }
     
    _PROTECTED2_PROTECTED3_PROTECTED0_PROTECTED4_PROTECTED1__注解来忽略设置多租户字段
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Service
    public class DemoService {
     
    @IgnoreTenantIdField
    public Role getRole() {
    return null;
    }
    }
     
    -- enable-pointcut-advisor-ignore-tenant-id
    multi-tenant:
    config:
    # 需要将此项配置设置为 true
    enable-pointcut-advisor-ignore-tenant-id: true
     
    • 需要注意的是,内部使用的___PROTECTED_15__0___PROTECTED_16__8___PROTECTED_17__1___PROTECTED_18__9___PROTECTED_19__2___PROTECTED_20__10___PROTECTED_21__3___PROTECTED_22__11___PROTECTED_23__4___PROTECTED_24__12___PROTECTED_25__5___PROTECTED_26__13___PROTECTED_27__6___PROTECTED_28__14___PROTECTED_29__7__
    sql
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    SELECT id, name, tenant_id
    FROM role
    WHERE tenant_id = 11
    -------------------------------------
     
    SELECT *
    FROM user s
    WHERE s.name = '333'
    AND s.tenant_id = 11
    -------------------------------------
     
    SELECT tenant_id
    FROM people
    WHERE id IN (
    SELECT id
    FROM user s
    WHERE s.tenant_id = 11
    )
    AND tenant_id = 11
    -------------------------------------
     
    SELECT tenant_id
    FROM people
    WHERE id IN (
    SELECT id
    FROM user s
    WHERE s.tenant_id = 11
    )
    AND id IN (
    SELECT u.id
    FROM user u
    WHERE u.tenant_id = 11
    )
    AND tenant_id = 11
    -------------------------------------
     
    SELECT tenant_id
    FROM people
    WHERE id IN (
    SELECT id
    FROM user s
    WHERE s.tenant_id = 11
    )
    AND id IN (
    SELECT u.id
    FROM user u
    WHERE u.tenant_id = 11
    )
    AND tenant_id IN (
    SELECT u.tenant_id
    FROM user u
    WHERE u.tenant_id = 11
    )
    AND tenant_id = 11
    -------------------------------------
     
    SELECT p.tenant_id
    , (
    SELECT u.name
    FROM user u
    WHERE u.id = p.user_id
    AND u.tenant_id = 11
    )
    FROM people p
    WHERE p.tenant_id = 11
    -------------------------------------
     
    SELECT p.tenant_id
    , (
    SELECT u.name
    FROM user u
    WHERE u.id = p.user_id
    AND u.tenant_id = 11
    )
    , (
    SELECT s.name
    FROM user s
    WHERE s.id = p.user_id
    AND s.tenant_id = 11
    )
    FROM people p
    WHERE p.tenant_id = 11
    -------------------------------------
     
    SELECT p.tenant_id
    , (
    SELECT u.name
    , (
    SELECT s.name
    FROM user s
    WHERE s.id = p.user_id
    AND s.tenant_id = 11
    )
    FROM user u
    WHERE u.id = p.user_id
    AND u.tenant_id = 11
    )
    FROM people p
    WHERE p.tenant_id = 11
    -------------------------------------
     
    SELECT u.*
    FROM `user` u
    JOIN user_role ur
    ON ur.user_id = u.id
    AND ur.tenant_id = 11
    WHERE u.tenant_id = 11
    -------------------------------------
     
    SELECT u.*
    FROM `user` u
    JOIN user_role ur
    ON ur.user_id = u.id
    AND u.id = 22
    AND ur.tenant_id = 11
    WHERE u.tenant_id = 11
    -------------------------------------
     
    SELECT u.*
    , (
    SELECT ur.name
    FROM role r
    WHERE r.id = ur.role_id
    AND r.tenant_id = 11
    ) AS r_name
    FROM `user` u
    JOIN user_role ur
    ON ur.user_id = u.id
    AND u.id = 22
    AND ur.tenant_id = 11
    WHERE u.tenant_id = 11
    -------------------------------------
     
    SELECT u.*
    FROM `user` u
    JOIN user_role ur
    ON ur.user_id = u.id
    AND ur.role_id IN (
    SELECT r.id
    FROM role r
    WHERE r.tenant_id = 11
    )
    AND ur.tenant_id = 11
    WHERE u.tenant_id = 11
    -------------------------------------
     
    SELECT u.*
    FROM `user` u
    JOIN user_role ur
    ON ur.user_id = u.id
    AND ur.role_id IN (
    SELECT r.id
    FROM role r
    WHERE r.tenant_id = 11
    )
    AND ur.test_id IN (
    SELECT r.test_id
    FROM role r
    WHERE r.tenant_id = 11
    )
    AND ur.tenant_id = 11
    WHERE u.tenant_id = 11
    -------------------------------------
     
    SELECT u.*
    FROM `user` u
    LEFT JOIN user_role ur
    ON ur.user_id = u.id
    AND ur.tenant_id = 11
    WHERE u.tenant_id = 11
    -------------------------------------
     
    SELECT u.*
    FROM `user` u
    RIGHT JOIN user_role ur
    ON ur.user_id = u.id
    AND ur.tenant_id = 11
    WHERE u.tenant_id = 11
    -------------------------------------
     
    SELECT COUNT(*), id
    FROM `user`
    WHERE tenant_id = 11
    GROUP BY id
    HAVING COUNT(*) >= 1
    -------------------------------------
     
    SELECT EXISTS (
    SELECT *
    FROM `user`
    WHERE username = ?
    AND tenant_id = 11
    ) AS d
    -------------------------------------
     
    SELECT EXISTS (
    SELECT tenant_id
    FROM people
    WHERE id IN (
    SELECT id
    FROM user s
    WHERE s.tenant_id = 11
    )
    AND tenant_id = 11
    ) AS d
    -------------------------------------
     
    SELECT username
    FROM `user`
    WHERE tenant_id = 11
    UNION
    SELECT username
    FROM account
    WHERE tenant_id = 11
    -------------------------------------
     
    SELECT u.*, r.id AS r_id, r.NAME AS r_name
    FROM `user` u
    LEFT JOIN user_role ur
    ON ur.user_id = u.id
    AND ur.tenant_id = 11
    LEFT JOIN role r
    ON r.id = ur.role_id
    AND u.id = 22
    AND r.tenant_id = 11
    WHERE u.tenant_id = 11
    -------------------------------------
     
    SELECT u.*, r.id AS r_id, r.NAME AS r_name
    FROM `user` u
    LEFT JOIN user_role ur
    ON ur.user_id = u.id
    AND ur.tenant_id = 11
    LEFT JOIN role r
    ON r.id = ur.role_id
    AND u.id = 22
    AND r.tenant_id = 11
    LEFT JOIN menu m
    ON m.role_id = r.id
    AND m.tenant_id = 11
    WHERE u.tenant_id = 11
    -------------------------------------
     
    SELECT a, b
    FROM (
    SELECT *
    FROM table_a
    WHERE tenant_id = 11
    ) temp
    WHERE temp.a = 'a';
    -------------------------------------
     
    SELECT temp.*
    FROM (
    SELECT *
    FROM `user`
    WHERE tenant_id = 11
    ) temp
    JOIN user_role ur
    ON ur.user_id = temp.id
    AND ur.tenant_id = 11
    WHERE temp.a = 'a'
    AND temp.tenant_id = 11;
    -------------------------------------
     
    SELECT id, name, tenant_id
    FROM role
    WHERE tenant_id = 1
    AND tenant_id = 11
     
    _PROTECTED0__
    sql
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    UPDATE user u
    SET ds = ?, u.name = ?, id = 'fdf', ddd = ?
    WHERE id = ?
    AND u.tenant_id = 11
    -------------------------------------
     
    UPDATE user u
    SET ds = ?, u.name = ?, id = 'fdf', ddd = ?
    WHERE id IN (1, 2, 3)
    AND u.tenant_id = 11
    -------------------------------------
     
    UPDATE user u
    SET ds = ?, u.name = ?, id = 'fdf', ddd = ?
    WHERE id IN (
    SELECT ur.user_id
    FROM user_role ur
    WHERE ur.tenant_id = 11
    )
    AND u.tenant_id = 11
    -------------------------------------
     
    UPDATE user u
    SET ds = ?, u.name = ?, id = 'fdf', ddd = ?
    WHERE id IN (
    SELECT ur.user_id
    FROM user_role ur
    WHERE ur.id = 1
    AND ur.tenant_id = 11
    )
    AND u.tenant_id = 11
    -------------------------------------
     
    UPDATE `user` u
    JOIN user_role ur
    ON ur.user_id = u.id
    AND u.id = 111
    AND ur.tenant_id = 11
    SET u.qr_code = '1212'
    WHERE u.tenant_id = 11
    -------------------------------------
     
    UPDATE `user` u
    JOIN user_role ur
    ON ur.user_id = u.id
    AND u.id IN (
    SELECT urr.user_id
    FROM user_role urr
    WHERE urr.tenant_id = 11
    )
    AND ur.tenant_id = 11
    SET u.qr_code = '1212'
    WHERE u.tenant_id = 11
    -------------------------------------
     
    UPDATE user
    SET name = CASE
    WHEN id = 1 THEN 'name1'
    WHEN id = 2 THEN 'name2'
    WHEN id = 3 THEN 'name3'
    END
    WHERE id IN (11, 22, 33, 3)
    AND tenant_id = 11;
     
    _PROTECTED0__
    sql
    1
    2
    3
    4
    5
    INSERT INTO `user` (`id`, `username`, `password`, tenant_id)
    VALUES (?, ?, ?, 11),
    (?, ?, ?, 11),
    (?, ?, ?, 11)
     
    _PROTECTED0__
    sql
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    DELETE FROM user
    WHERE id = 1
    AND tenant_id = 11
    -------------------------------------
     
    DELETE FROM user
    WHERE id IN (
    SELECT id
    FROM user s
    WHERE s.tenant_id = 11
    )
    AND tenant_id = 11
    -------------------------------------
     
    DELETE FROM system_permission_data sp
    LEFT JOIN system_role_data_relation re
    ON sp.id = re.data_id
    AND re.tenant_id = 11
    LEFT JOIN system_role sr
    ON sr.id = re.role_id
    AND sr.tenant_id = 11
    WHERE sr.id = 1
    AND sp.tenant_id = 11
     
    评论(0)
    暂无评论来抢沙发吧~