Hibernate 租户隔离:使用切面自动添加 tenant_id 条件
可以使用 Hibernate 的拦截器(Interceptor)来实现自动应用 tenant_id 的租户条件。Interceptor 可以在 Hibernate 执行数据库操作之前和之后拦截并处理一些操作,比如在执行查询时自动添加租户条件。
具体实现步骤如下:
- 创建一个实现了 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;
}
//省略其他方法
}
- 在 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>
- 在业务逻辑中使用 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 语句中,从而保证每个租户只能访问自己的数据。
原文地址: https://www.cveoy.top/t/topic/oKKf 著作权归作者所有。请勿转载和采集!