我根据this article为Spring + Hibernate实现了动态数据源路由。我有几个具有相同结构的数据库,我需要选择运行每个特定查询的数据库。
在localhost上一切正常,但我担心这会如何在真正的网站环境中保持不变。他们使用一些静态上下文持有者来确定要使用的数据源:
public class CustomerContextHolder {
private static final ThreadLocal<CustomerType> contextHolder =
new ThreadLocal<CustomerType>();
public static void setCustomerType(CustomerType customerType) {
Assert.notNull(customerType, "customerType cannot be null");
contextHolder.set(customerType);
}
public static CustomerType getCustomerType() {
return (CustomerType) contextHolder.get();
}
public static void clearCustomerType() {
contextHolder.remove();
}
}
它包含在一些ThreadLocal容器中,但究竟是什么意思呢?当两个Web请求并行调用此代码时会发生什么:
CustomerContextHolder.setCustomerType(CustomerType.GOLD);
//<another user will switch customer type here to CustomerType.SILVER in another request>
List<Item> goldItems = catalog.getItems();
是否每个Web请求都包装在Spring MVC中自己的线程中?其他网络用户是否可以看到CustomerContextHolder.setCustomerType()
更改?我的控制器有synchronizeOnSession=true
。
如何确保在我为当前用户运行所需查询之前,没有其他人会切换数据源?
感谢。
答案 0 :(得分:5)
是否每个Web请求都包装在Spring MVC中自己的线程中?
是的,但这与Spring MVC无关,容器正在这样做(容器有一个线程池并选择其中一个来处理每个请求)。
CustomerContextHolder.setCustomerType()更改是否会对其他网络用户可见?
没有。根据定义,ThreadLocal
是线程的本地。来自javadoc:
此类提供线程局部变量。这些变量与它们的正常对应物的不同之处在于,访问其中的每个线程(通过其
get
或set
方法)都有自己独立初始化的变量副本。ThreadLocal
实例通常是希望将状态与线程相关联的类中的私有静态字段(例如,用户ID或事务ID)。
set
中的ThreadLocal
对其他线程不可见。你应该没事的