# jpa-tenant-plugin
**Repository Path**: czykeith/jpa-tenant-plugin
## Basic Information
- **Project Name**: jpa-tenant-plugin
- **Description**: 本插件基于springboot实现jpa基于数据库字段实现租户数据隔离功能(当前自动创建租户字段仅支持MySql数据库)
- **Primary Language**: Java
- **License**: AGPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 7
- **Forks**: 1
- **Created**: 2023-10-25
- **Last Updated**: 2025-06-19
## Categories & Tags
**Categories**: database-dev
**Tags**: None
## README
# jpa-tenant-plugin 单字段租户版本
**本插件基于springboot实现jpa基于数据库字段实现租户数据隔离功能(当前自动创建租户字段仅支持MySql数据库)**
**注意事项:本插件基于spring aop实现,使用@JpaTenant时,需要注意注解失效的场景**
**============本插件的使用方法============**
* 在pom文件中加入插件依赖,示例如下:
```
com.keith
jpa-tenant-plugin
1.0
```
* 在YML文件中添加JPA拦截与插件相关配置,示例如下:
```
spring:
jpa:
tenant:
enable: true # 是否开启租户解析,租户插件总开关,默认为false
defaultTenant: true #没有JpaTenant注解情况下默认是否做租户处理,默认为true
tenantColumn: tenant_id #租户数据库字段名称,默认为tenant_id
tenantColumnType: Long #租户字段数据类型,仅支持Long、String两种类型,默认为Long
ignoreTables: sys_tenant #忽略租户处理的表名,多个以逗号分隔,也可以以注解方法忽略
log: false #是否开启调试日志 开启后将打印处理器与处理后的sql语句,默认为false
penetration: false #是否开启租户穿透,注解优先级更高
filterTenantIdValues: #配置需要替换处理的租户ID,例如:配置为0,则到检测到sql语句中租户字段的值为0时,则会用当前上下文中的租户ID替换
properties:
hibernate:
ejb:
interceptor: com.keith.jpa.tenant.TenantJpaEmptyInterceptor #拦截jpa对象,兼容保存操作jdbc预处理无法自动处理租户的问题,如果jpa保存操作需要自动处理租户请配置该项
session_factory:
statement_inspector: com.keith.jpa.tenant.TenantJpaInspector #配置jpa租户处理拦截器
```
* 租户处理上下文处理,通过TenantContextHolder类进行处理,该类针对异步执行时无法获取ThreadLocal的租户信息进行了处理(通常情况下在拦截器或者过滤器中统一处理),使用方法如下:
```
TenantContextHolder.setTenantId(user.getTenantId()); #在需要用到租户信息的入口进行当前线程用户租户信息设置,此设置作用于当前线程以及当前线程创建的异步线程以及线程池
TenantContextHolder.removeTenantId(); #使用完成后清理当前线程的租户信息
```
* 线程池中租户处理上下文处理,由于普通线程池在使用TenantContextHolder上下文时会造成线程复用导致的数据异常,因此本插件提供了租户线程池工具类:TenantThreadPoolUtils;在线程池中需要使用到TenantContextHolder租户信息的时候必须使用
该工具类获取线程池;如果有其他自定义线程需求,请参考TransmittableThreadLocal的使用进行线程池创建。
```
ExecutorService executorService = TenantThreadPoolUtils.getThreadPool(4, 8, 10000, "execute-pool");
```
* @JpaTenant注解的使用方法,注解的优先级高于配置文件中defaultTenant的配置,但是无法覆盖ignoreTables设置;可以在类或者方法上使用该注解(方法注解优先级高于类上注解);支持嵌套注解;建议在dao层进行注解,以最小粒度进行控制,使用示例如下:
```
#@JpaTenant注解中属性作用:
#tenant: 是否忽略租户处理,true,添加注解后tenant的设置将覆盖配置中defaultTenant字段,但是无法覆盖ignoreTables设置
#tenentId: 当前操作的租户ID,默认为空,添加该属性注解后,租户操作将以该值作为优先值,如果该属性为空,将以TenantContextHolder中的租户ID为准
#1、忽略当前操作的租户处理
@JpaTenant(tenant = false)
public interface JobCfjDao extends CcbRepository
#2、当前操作需要做租户处理,且设置租户ID
@JpaTenant(tenentId = "租户Id")
public interface ProgDefDao extends CcbRepository
#3、当前操作需要做租户处理,租户ID从线程上下文中获取
@JpaTenant
public interface ProgDefDao extends CcbRepository
```
* 各参数优先级说明
配置spring.jpa.tenant.ignoreTables>JpaTenant.tenant>配置spring.jpa.tenant.defaultTenant
JpaTenant.tenantId>TenantContextHolder.setTenantId();
* 租户穿透的实现,实现TenantPenetration接口,返回穿透查询逻辑
```
@Component
public class Test implements TenantPenetration{
@Override
public List