JPA+Hibernate 多租户,使用租户标识@TenantId隔离的实现

发布时间 2023-03-22 21:11:07作者: 代码红了一大片

在多租户的场景下,需要对不同租户的数据进行隔离,但是我们不能在每个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 去自动帮我们拼接的,这样我们的租户隔离就实现啦