一、概述
基于Spring动态配置多数据源,在大型的应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效的提高系统的水平伸缩性,而这样的解决方案就会补同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求以及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据。
Spring配置多个数据源的方式和具体使用过程,Spring对于多数据源,以数据库表为参照,大体上可以分为两大类情况:
1、表级上的跨数据库,即对于不同的数据库却有不相同的表(表名和表结构完全相同)。
2、非表级上的跨数据库,即多个数据源不存在相同的表。
Spring2.x的版本中采用Proxy模式,就是在方案中实现一个虚拟的数据源,并且采用它来封装数据源选择逻辑,这样就可以有效的地将数据源选择逻辑从Client中分离出来,Client提供选择所需上下文,由虚拟的DataSource根据Client提供的上下文来实现数据源的选择。具体实现就是,虚拟的DataSource仅需要继承AbstractRoutingDataSource实现determineCurrentLookupKey()在其中封装数选择逻辑。
二、前期准备
1、搭建好ssi的web架构
2、创建好oracle数据库实例,该实例中创建实例为orcl和n8web两个数据库实例,并且创建好表空间和对应的数据库表
3、配置好tomcat容易,能正常发布web工程。
4、每个实例中创建如下脚本的表和添加数据,为了区分web能动态的切换数据源,请在两个实例中添加不同的数据即可。
CREATE TABLE UserInfo ( id NUMBER(10) NOT NULL, username VARCHAR(32), password VARCHAR(32), emial VARCHAR(15), sex VARCHAR(10), brithday NUMBER(32), province VARCHAR(32), city VARCHAR(32), state VARCHAR(32), realname VARCHAR(32), college VARCHAR(255), highschool VARCHAR(255), gradeschool VARCHAR(32), regtime NUMBER(32), logintime NUMBER(32), PRIMARY KEY (id) ); insert into UserInfo values(1,‘zhangsan‘,‘123456‘,‘[email protected]‘,‘男‘,null,‘湖南‘,‘长沙‘,‘健康‘,‘张三‘,‘北京大学‘,null,null,null,null); insert into UserInfo values(2,‘zhangsan02‘,‘123456‘,‘[email protected]‘,‘女‘,null,‘北京‘,‘北京‘,‘健康‘,‘张三‘,‘北京大学‘,null,null,null,null); insert into UserInfo values(3,‘zhangsan03‘,‘123456‘,‘[email protected]‘,‘男‘,null,‘湖南‘,‘长沙‘,‘健康‘,‘张三‘,‘北京大学‘,null,null,null,null); insert into UserInfo values(4,‘zhangsan04‘,‘123456‘,‘[email protected]‘,‘女‘,null,‘深圳‘,‘深圳‘,‘健康‘,‘张三‘,‘北京大学‘,null,null,null,null); insert into UserInfo values(5,‘zhangsan05‘,‘123456‘,‘[email protected]‘,‘男‘,null,‘湖南‘,‘长沙‘,‘健康‘,‘张三‘,‘北京大学‘,null,null,null,null); insert into UserInfo values(6,‘zhangsan06‘,‘123456‘,‘[email protected]‘,‘女‘,null,‘广东‘,‘广州‘,‘健康‘,‘张三‘,‘北京大学‘,null,null,null,null); insert into UserInfo values(7,‘zhangsan07‘,‘123456‘,‘[email protected]‘,‘男‘,null,‘湖南‘,‘长沙‘,‘健康‘,‘张三‘,‘北京大学‘,null,null,null,null); insert into UserInfo values(8,‘zhangsan08‘,‘123456‘,‘[email protected]‘,‘女‘,null,‘湖北‘,‘武汉‘,‘健康‘,‘张三‘,‘北京大学‘,null,null,null,null);
三、实现步骤
1、搭建基于struts2+spring+ibatis+oracle10g的web架构(该过程略)
2、创建数据源的名称常量类
public class DataSourceConst { public static final String Admin="1"; public static final String User="2"; }
3、建立一个获得和设置上下文环境的类,主要负责改变上下文数据源的名称
public class DataSourceContextHolder { private static final ThreadLocal contextHolder = new ThreadLocal(); // 线程本地环境 // 设置数据源类型 public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } // 获取数据源类型 public static String getDataSourceType() { return (String) contextHolder.get(); } // 清除数据源类型 public static void clearDataSourceType() { contextHolder.remove(); } }
4、建立动态数据源类,注意这个类必须继承AbstractRoutingDataSource,且实现方法determineCurrentLookupKey,该方法返回一个Object,一般是返回字符串:
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { // TODO Auto-generated method stub return null; } }
5、编写Spring的配置文件配置多个数据源
5.1、读取数据源信息的配置,这里我们是从tomcat容器的conf目录下读取jdbc.properties配置文件,该配置文件信息在后面给出。
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value> file:${webapp.root}\..\..\conf/jdbc.properties </value> </list> </property> </bean>
5.2、配置数据源的配置
<!-- 数据源1配置 --> <bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc1.url}" /> <property name="username" value="${jdbc1.username}" /> <property name="password" value="${jdbc1.password}" /> </bean> <!-- 数据源1配置 --> <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc2.url}" /> <property name="username" value="${jdbc2.username}" /> <property name="password" value="${jdbc2.password}" /> </bean> <!-- 编写spring 配置文件的配置多数源映射关系 --> <bean class="com.song.datasource.DynamicDataSource" id="dataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry value-ref="dataSource1" key="1"></entry> <entry value-ref="dataSource2" key="2"></entry> </map> </property> <!--默认采用dataSource1--> <property name="defaultTargetDataSource" ref="dataSource1"> </property> </bean>
说明:上述为两个数据库实例的配置信息,第三段中编写Spring配置文件的多数据源映射关系是关键,这里映射dataSource1和dataSource2对应的key值为1和2,在我们程序中就可以根据这两个key值来做判断,同时还配置了默认的数据源为dataSource1.
5.3、jdbc.properties配置信息如下,这里分别配置了orcl和n8web两个oracle实例的配置信息,账户和口令均为n8_web,在创建数据库表空间和用户时随便取名称。
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver jdbc1.url=jdbc:oracle:thin:@127.0.0.1:1521:n8web jdbc1.username=n8_web jdbc1.password=n8_web jdbc2.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl jdbc2.username=n8_web jdbc2.password=n8_web
说明:从上述配置文件可以看出,dataSource1数据源对应的是n8web这个实例,dataSource2对应的是orcl实例。两个实例创建的账户信息均为n8_web(随意)
四、运行结果如下:
图-1
上图中,前期准备工作中,在数据源1的数据库实例中插入了11条数据,在数据源2的实例中插入了8条数据,下面点击【数据源选择】查看输出的数据列表是否正确,如下:
图-2
选择【数据源2】时,查询出来的数据如下:
图-3
采用PL/SQL工具来验证下是否正确,两个数据库实例中的数据如下:
图-4
图-5
结论:测试的结果是正确的,能根据条件达到动态切换数据源的目的
源码配置文件等下载:(包含源码、各种配置文件、数据库脚本等)
基于Struts2 Spring ibatis Oracle10g架构 多数据源动态切换实例,码迷,mamicode.com