数据源配置
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="multipleDataSource" />
<property name="packagesToScan">
<list>
<!-- 可以加多个包 -->
<value>com.lei.demo.entity</value>
</list>
</property>
<propertyname="hibernateProperties">
<props>
<!-- <propkey="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>-->
<propkey="hibernate.dialect">${hibernate.dialect}</prop>
<propkey="hibernate.show_sql">${hibernate.show_sql}</prop>
<!-- <propkey="hibernate.current_session_context_class">thread</prop>-->
</props>
</property>
</bean>
<bean id="dataSource"class="com.alibaba.druid.pool.DruidDataSource"init-method="init" destroy-method="close">
<property name="url"value="${jdbc.url}" />
<property name="username"value="${jdbc.user}" />
<property name="password"value="${jdbc.pass}" />
<property name="filters"value="stat" />
<property name="maxActive"value="20" />
<propertyname="initialSize" value="1" />
<property name="maxWait"value="60000" />
<property name="minIdle"value="1" />
<propertyname="timeBetweenEvictionRunsMillis" value="3000" />
<propertyname="minEvictableIdleTimeMillis" value="300000" />
<propertyname="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle"value="true" />
<propertyname="testOnBorrow" value="false" />
<propertyname="testOnReturn" value="false" />
<propertyname="poolPreparedStatements" value="true" />
<propertyname="maxPoolPreparedStatementPerConnectionSize" value="20"/>
</bean>
<bean id="dataSource2"class="com.alibaba.druid.pool.DruidDataSource"init-method="init" destroy-method="close">
<property name="url"value="${jdbc2.url}" />
<property name="username"value="${jdbc2.user}" />
<property name="password"value="${jdbc2.pass}" />
<property name="filters"value="stat" />
<property name="maxActive"value="20" />
<propertyname="initialSize" value="1" />
<property name="maxWait"value="60000" />
<property name="minIdle"value="1" />
<propertyname="timeBetweenEvictionRunsMillis" value="3000" />
<propertyname="minEvictableIdleTimeMillis" value="300000" />
<propertyname="validationQuery" value="SELECT 'x'" />
<propertyname="testWhileIdle" value="true" />
<property name="testOnBorrow"value="false" />
<propertyname="testOnReturn" value="false" />
<propertyname="poolPreparedStatements" value="true" />
<propertyname="maxPoolPreparedStatementPerConnectionSize" value="20"/>
</bean>
<bean id="multipleDataSource"class="com.lei.demo.MultipleDataSource">
<propertyname="defaultTargetDataSource" ref="dataSource"/>
<property name="targetDataSources">
<map>
<!-- 注意这里的value是和上面的DataSource的id对应,key要和下面的CustomerContextHolder中的常量对应 -->
<entryvalue-ref="dataSource" key="dataSource"/>
<entryvalue-ref="dataSource2" key="dataSource2"/>
</map>
</property>
</bean>
2、配置拦截器
<beanclass="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
<beanclass="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<propertyname="interceptors">
<list>
<bean class="com.ug.web.ControllerInterceptor"/>
</list>
</property>
</bean>
<beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
这里注意:RequestMappingHandlerMapping,否则拦截器中
public boolean preHandle(HttpServletRequest request, HttpServletResponseresponse, Object arg2) throws Exception {
arg2 会是Controller而不是method
3、拦截器
HandlerMethod handlerMethod = (HandlerMethod)arg2;
Method method =handlerMethod.getMethod();
DataSourceSetter annotation =method.getAnnotation(DataSourceSetter.class);
if(annotation == null ||annotation.source().equals("")){
//设置默认数据源
CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE1);
} else {
CustomerContextHolder.setCustomerType(annotation.source());
}
根据注解,自动设置数据源
4、数据源
public abstract class CustomerContextHolder {
public final static String DATA_SOURCE1 = "dataSource";
public final static String DATA_SOURCE2 ="dataSource2";
private static final ThreadLocal<String> contextHolder =new ThreadLocal<String>();
public static void setCustomerType(String customerType) {
contextHolder.set(customerType);
}
public static String getCustomerType() {
return contextHolder.get();
}
public static void clearCustomerType() {
contextHolder.remove();
}
}
public class MultipleDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return CustomerContextHolder.getCustomerType();
}
}
5、注解
//method级的数据源
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSourceSetter{
String source() default "";
}
空,则设置默认数据源
//Control级的数据源
@Target(ElementType.Type)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSourceSetter{
String source() default "";
}
空,则设置默认数据源
放在method上的
@DataSourceSetter(source= CustomerContextHolder.DATA_SOURCE2)
注意:CustomerContextHolder.setCustomerType(annotation.source());
这种方式,设置过一次之后,后面的关联都是按照此数据源来进行。所以在多数据源系统中,必须自动按照配置,每次都需要设置数据源。否则会因为数据源没有切换回来,导致查询失败。