自定义过滤器
提供抽象实体基类
首先,提供一个MappedSuperclass
超类型,让所有需要多租户管理的实体类都继承它
- Java
- Kotlin
TenantAware.java
@MappedSuperclass
public interface TenantAware {
String tenant();
}
TenantAware.kt
@MappedSuperclass
interface TenantAware {
val tenant: String
}
任何需要支持多租户的实体类型都可以继承TenantAware
,例如Book
- Java
- Kotlin
Book.java
@Entity
public interface Book extends TenantAware {
...省略代码...
}
Book.kt
@Entity
interface Book : TenantAware {
...省略代码...
}
提示
诚然,可以不定义抽象类型,直接对实体类型施加过滤器,这没有任何问题。
然而,更推荐的方法是从实体中提取抽象类型,这样一个过滤器可以过滤多种实体类型。
更重要的是,MappedSupperClass
支持多继承,即实体类型可以从多个超类型继承。多继承和全局过滤器相结合后可以带来惊人的灵活性。
定义过滤器
假设Spring上下文中有一个类型为TenantProvider
的对象,其Java方法get()
和kotlin属性tenant
用于从当前操作者身份信息中提取所属租户。定义如下过滤器
- Java下,拦截器需实现
org.babyfish.jimmer.sql.filter.Filter
接口, - Kotlin下,拦截器需实现
org.babyfish.jimmer.sql.kt.filter.KFilter
接口。
如果使用Spring托管,代码方式如下:
- Java
- Kotlin
@Component
public class TenantFilter implements Filter<TenantAwareProps> {
private final TenantProvider tenantProvider;
public TenantFilter(TenantProvider tenantProvider) {
this.tenantProvider = tenantProvider;
}
@Override
public void filter(FilterArgs<TenantAwareProps> args) {
String tenant = tenantProvider.get();
if (tenant != null) {
args.where(args.getTable().tenant().eq(tenant));
}
}
}
@Component
class TenantFilter(
private val tenantProvider: TenantProvider
) : KFilter<TenantAware> {
override fun filter(args: KFilterArgs<TenantAware>) {
tenantProvider.tenant?.let {
args.apply {
where(table.tenant.eq(it))
}
}
}
}
Java和Kotlin的过滤器定义略有不同
-
Java中,
Filter
的范型参数为TenantAwareProps
,这是预编译器针对抽象类型TenantAware
自动生成的代码之一 -
Kotlin中,
KFilter
的范型参数是抽象类型TenantAware
本身
TenantFilter
过滤抽象类型TenantAware
,对于任何直接或间接继承抽象接口TenantAware
的实体而言,其查询都会被这个过滤器处理,自动添加where条件。
TenantFilter
内部,首先从提取当前操作者身份信息中提取其所属租户,如果所属租户非null,则使用它来过滤数据,只查询和指定租户匹配的数据。