JPA+Hibernate 多租户,使用租户标识@TenantId隔离的实现
在多租户的场景下,需要对不同租户的数据进行隔离,但是我们不能在每个sql后面都拼接对应的租户标识,我们就可以使用一个注解@TenantId 来进行租户的标识切换,在添加了这个注解的实体类,执行sql时,就会进行拼接一个对应的租户标识
具体的实现如下
1、在实体类中标识该注解
@EqualsAndHashCode(callSuper = false)
@Entity
@Data
public class Evaluation extends AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String id;
@TenantId
@Column(name = "tenant_code")
private String tenantCode;
}
对于AbstractEntity可以查看上一篇 只加该注解也不会直接起作用,还需要另一个配置
2、这个类是由Hibernate提供的用于识别tenantId的类,当每次执行sql语句被拦截就会调用这个类中的方法来获取tenantId
/**
* 实现租户的切换
* 这个类是由Hibernate提供的用于识别tenantId的类,当每次执行sql语句被拦截就会调用这个类中的方法来获取tenantId
*/
@Component
public class PartitionedTenantIdentifierResolver implements CurrentTenantIdentifierResolver, HibernatePropertiesCustomizer {
@Override
public String resolveCurrentTenantIdentifier() {
return Optional.ofNullable(SecurityContextHolder.getTenantCode()).orElse("Default");
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
//SecurityContextHolder.getTenantCode()上下文获取当前租户标识
@Override
public void customize(Map<String, Object> hibernateProperties) {
hibernateProperties.put(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, this);
}
}
这样就完成了这个注解的配置,接下来看看区别
如果我们要查询该用户的详情
#没有使用该注解时
select * from user;
#使用该注解时,假设租户的tenantCode="baidu",对应的sql就如下
select * from user where tenantCode="baidu";
tenantCode="baidu" 是 Hibernate 去自动帮我们拼接的,这样我们的租户隔离就实现啦