可以使用 Hibernate 的拦截器(Interceptor)来实现自动应用 tenant_id 的租户条件。Interceptor 可以在 Hibernate 执行数据库操作之前和之后拦截并处理一些操作,比如在执行查询时自动添加租户条件。

具体实现步骤如下:

  1. 创建一个实现了 Interceptor 接口的拦截器类,重写 onPrepareStatement 方法,在 SQL 语句中自动添加租户条件。
public class TenantInterceptor implements Interceptor {
    
    private final ThreadLocal<Long> tenantIdHolder = new ThreadLocal<>();

    public void setTenantId(Long tenantId) {
        tenantIdHolder.set(tenantId);
    }
    
    @Override
    public String onPrepareStatement(String sql) {
        Long tenantId = tenantIdHolder.get();
        if (tenantId != null) {
            return 'select * from ' + sql + ' where tenant_id = ' + tenantId;
        }
        return sql;
    }
    
    //省略其他方法
}
  1. 在 Spring 中配置拦截器,并将其注入到 SessionFactory 中。
<bean id="tenantInterceptor" class="com.example.TenantInterceptor" />

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.example.model" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
        </props>
    </property>
    <property name="entityInterceptor" ref="tenantInterceptor" />
</bean>
  1. 在业务逻辑中使用 ThreadLocal 将租户 ID 传递给拦截器。
@Service
public class UserService {

    @Autowired
    private SessionFactory sessionFactory;

    public List<User> getUsersByTenant(Long tenantId) {
        TenantInterceptor tenantInterceptor = (TenantInterceptor) sessionFactory
            .getHibernateSessionFactory()
            .getCurrentSession()
            .getSessionFactory()
            .getEntityInterceptor();
        tenantInterceptor.setTenantId(tenantId);
        Session session = sessionFactory.getCurrentSession();
        List<User> userList = session.createQuery('from User').list();
        return userList;
    }
}

这样,在执行查询时,拦截器会自动将租户条件加入到 SQL 语句中,从而保证每个租户只能访问自己的数据。

Hibernate 租户隔离:使用切面自动添加 tenant_id 条件

原文地址: https://www.cveoy.top/t/topic/oKKf 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录