用注解方式实现动态切切换数据源
—jdbc配置—
jdbc.master.driver=com.mysql.jdbc.Driver
jdbc.master.url=jdbc:mysql://192.168.10.160:3306/data_main?useUnicode=true&characterEncoding=utf-8
jdbc.master.user=zxuser
jdbc.master.password=123456
jdbc.slave.driver=com.mysql.jdbc.Driver
jdbc.slave.url=jdbc:mysql://192.168.10.160:3306/data_salve?useUnicode=true&characterEncoding=utf-8
jdbc.slave.user=zxuser
jdbc.slave.password=123456
jdbc.initialSize=10
jdbc.maxActive=100
jdbc.maxIdle=5
jdbc.minIdle=2
——————spring 配置————————–
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:jdbc.properties" />
</bean>
<bean id="masterDataSources" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.master.driver}" />
<property name="url" value="${jdbc.master.url}" />
<property name="username" value="${jdbc.master.user}" />
<property name="password" value="${jdbc.master.password}" />
<!-- 数据库连接池配置 -->
<property name="initialSize" value="${jdbc.initialSize}" /><!--
初始化连接数量 -->
<property name="maxActive" value="${jdbc.maxActive}" /><!-- 最大连接数量 -->
<property name="maxIdle" value="${jdbc.maxIdle}" /><!-- 最大空闲连接数量 -->
<property name="minIdle" value="${jdbc.minIdle}" /><!-- 最小空闲连接数量 -->
</bean>
<bean id="slaveDataSources" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.slave.driver}" />
<property name="url" value="${jdbc.slave.url}" />
<property name="username" value="${jdbc.slave.user}" />
<property name="password" value="${jdbc.slave.password}" />
<!-- 数据库连接池配置 -->
<property name="initialSize" value="${jdbc.initialSize}" /><!--
初始化连接数量 -->
<property name="maxActive" value="${jdbc.maxActive}" /><!-- 最大连接数量 -->
<property name="maxIdle" value="${jdbc.maxIdle}" /><!-- 最大空闲连接数量 -->
<property name="minIdle" value="${jdbc.minIdle}" /><!-- 最小空闲连接数量 -->
</bean>
<bean id="dataSource" class="com.shop.jdbc.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="masterDataSources" key="masterDataSources"></entry>
<entry value-ref="slaveDataSources" key="slaveDataSources"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="masterDataSources"></property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml" />
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath*:com/shop/mapper/*/*Mapper.xml" />
</bean>
<bean id="transactionManager" class="com.shop.jdbc.MyDataSourceTransactionManager">
<property name="dataSource" ref="dataSource">
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
//动态数据源DynamicDataSource
package com.shop.jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Wrapper;
import java.util.Map;
import javax.activation.DataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.jdbc.datasource.lookup.DataSourceLookup;
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
public class DynamicDataSource extends AbstractRoutingDataSource implements
InitializingBean {
private Map<String, DataSource> masterDataSources;
private Map<String, DataSource> slaveDataSources;
private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
public Map<String, DataSource> getMasterDataSources() {
return masterDataSources;
}
public void setMasterDataSources(Map<String, DataSource> masterDataSources) {
this.masterDataSources = masterDataSources;
}
public Map<String, DataSource> getSlaveDataSources() {
return slaveDataSources;
}
public void setSlaveDataSources(Map<String, DataSource> slaveDataSources) {
this.slaveDataSources = slaveDataSources;
}
public DataSourceLookup getDataSourceLookup() {
return dataSourceLookup;
}
public void setDataSourceLookup(DataSourceLookup dataSourceLookup) {
this.dataSourceLookup = dataSourceLookup;
}
@Override
public Connection getConnection() throws SQLException {
return determineTargetDataSource().getConnection();
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
return determineTargetDataSource().getConnection();
}
@Override
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> iface) throws SQLException {
if (iface.isInstance(this)) {
return (T) this;
}
return ((Wrapper) determineTargetDataSource()).unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return (iface.isInstance(this) || ((Wrapper) determineTargetDataSource())
.isWrapperFor(iface));
}
protected Object resolveSpecifiedLookupKey(Object lookupKey) {
return lookupKey;
}
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDbType();
}
}
package com.shop.jdbc;
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}
public static String getDbType() {
return ((String) contextHolder.get());
}
//这个方法必不可少 否则切换数据库的时候有缓存现在
public static void clearDbType() {
contextHolder.remove();
}
}
//注解的方式切换数据源
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String description() default "";
}
//server上添加注解
@Override
@DataSource(description = "slaveDataSources")
public List<Map<String, Object>> queryForPageSlave(String fields,
String orderBy, int pageIndex, int pageSize, Ref<Integer> record,
Parameter... where) throws Exception {
return userdao.queryListForPage(fields, pageIndex, pageSize, record,
orderBy, where);
}