如何为AbstractRoutingDataSource安全频繁的DataSource切换?

时间:2010-06-15 19:26:58

标签: java hibernate spring

我根据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

如何确保在我为当前用户运行所需查询之前,没有其他人会切换数据源?

感谢。

1 个答案:

答案 0 :(得分:5)

  

是否每个Web请求都包装在Spring MVC中自己的线程中?

是的,但这与Spring MVC无关,容器正在这样做(容器有一个线程池并选择其中一个来处理每个请求)。

  

CustomerContextHolder.setCustomerType()更改是否会对其他网络用户可见?

没有。根据定义,ThreadLocal是线程的本地。来自javadoc:

  

此类提供线程局部变量。这些变量与它们的正常对应物的不同之处在于,访问其中的每个线程(通过其getset方法)都有自己独立初始化的变量副本。 ThreadLocal实例通常是希望将状态与线程相关联的类中的私有静态字段(例如,用户ID或事务ID)。

set中的ThreadLocal对其他线程不可见。你应该没事的