1、使用场景:
以自己为例,现有一个后台管理系统管理着游戏数据。以前是一个后台地址对应一个后台管理一个游戏后台,现在改进为一个后台管理多个游戏数据。在登录或者其他地方切换下就可以查询数据。
2、步骤分为:多数据源配置和动态切换配置和事务+OpenSessionInViewFilter配置
先不考虑动态切换配置,一个datasource对应一个sessionFactory对应一个hibernateTemplate对应一个transactionManager对应一个OpenSessionInViewFilter
在多数据源模式下有多个sessionFactory,所以配置hibernateTemplate,transactionManager,OpenSessionInViewFilter的时候要指定sessionFactory!
<filter> <filter-name>OpenSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>sessionFactoryBeanName</param-name> <param-value>sessionFactory1</param-value> </init-param> </filter> <filter-mapping> <filter-name>OpenSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping><filter>
<filter-name>OpenSessionInViewFilter4</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>sessionFactoryBeanName</param-name> <param-value>sessionFactory4</param-value> </init-param> </filter> <filter-mapping> <filter-name>OpenSessionInViewFilter4</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<bean id="transactionManager4"
class="org.springframework.orm.hibernate3.HibernateTransactionManager" autowire="byName"> <property name="sessionFactory" ref="sessionFactory4"></property> </bean>
其中transactionManager有一个问题,就是配置aop的时候要注意2个transactionManager不重叠。
3、在dao中注入不同的sessionfactory/hibernateTemplate 操作各自所属数据源数据
HibernateTemplate hibernateTemplate;
@Resource(name = "hibernateTemplate4")
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
HibernateTemplate hibernateTemplate;
@Resource(name = "hibernateTemplate1")
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
4、动态切换数据源(用来切换服务器)
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final Logger log = Logger.getLogger(DynamicDataSource.class);
@Override
protected Object determineCurrentLookupKey() {
String i= CustomerContextHolder.getCustomerType();
return i;
}
}
<bean id="dataSource00" class="com.xxx.util.DynamicDataSource">
<property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="2" value-ref="dataSource2" /> <entry key="1" value-ref="dataSource1" /> </map> </property> <property name="defaultTargetDataSource" ref="dataSource1" /> </bean>
动态切换很简单,datasource配置改为AbstractRoutingDataSource实现类指定一个defaultTargetDataSource和targetDataSources
在需要切换的地方
public class CustomerContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal();
public static void setCustomerType(String customerType) {
contextHolder.set(customerType);
}
public static String getCustomerType() {
return (String) contextHolder.get();
}
public static void clearCustomerType() {
contextHolder.remove();
}
}
CustomerContextHolder.setCustomerType("2");//切换key为2的数据源
User uu = userService.get(User.class, "id = ?", 3l);
就这样查询出来的就是第二个数据源的数据了
不出意外的话,是可以看到效果的。如果出现了事务问题就要查找下是否sessionfactory和aop配置正确。如果你把一个service类在aop中配置2次会出现错误的。
多数据源:管理系统数据源+游戏数据源
动态切换:游戏数据各服务器之间切换。