SSM项目实现连接两个mysql数据库
最近做项目需要用到另一个数据库的内容,多方查找终于实现了功能。
我们都知道,在SSM框架中,我们在applicationContext.xml配置文件中添加数据源就可以实现数据库增删改查,但是只能连接一个数据库,这个时候我们就要从spring提供的源码下手看看有没有有关数据源切换的方法,找到关键源码(AbstractRoutingDataSource类,该类就相当于一个dataSource的调度者,用于根据key值来进行切换对应的dataSource。
AbstractRoutingDataSource类:
@Override
public Connection getConnection() throws SQLException {
return determineTargetDataSource().getConnection();
} @Override
public Connection getConnection(String username, String password) throws SQLException {
return determineTargetDataSource().getConnection(username, password);
} /**
* Retrieve the current target DataSource. Determines the
* {@link #determineCurrentLookupKey() current lookup key}, performs
* a lookup in the {@link #setTargetDataSources targetDataSources} map,
* falls back to the specified
* {@link #setDefaultTargetDataSource default target DataSource} if necessary.
* @see #determineCurrentLookupKey()
*/
protected DataSource determineTargetDataSource() {
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
Object lookupKey = determineCurrentLookupKey();
DataSource dataSource = this.resolvedDataSources.get(lookupKey);
if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
dataSource = this.resolvedDefaultDataSource;
}
if (dataSource == null) {
throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
}
return dataSource;
} /**
* Determine the current lookup key. This will typically be
* implemented to check a thread-bound transaction context.
* <p>Allows for arbitrary keys. The returned key needs
* to match the stored lookup key type, as resolved by the
* {@link #resolveSpecifiedLookupKey} method.
*/
protected abstract Object determineCurrentLookupKey();
可以看出方法getConnection()调用的determineTargetDataSource则是关键方法,这个方法返回了具体使用的是哪个数据库;而
determineCurrentLookupKey()方法来返回当前数据源的key值。
将返回的key值在resolvedDataSources这个map中找到对应的value(当前使用的数据源)。
源码:
@Override
public void afterPropertiesSet() {
if (this.targetDataSources == null) {
throw new IllegalArgumentException("Property 'targetDataSources' is required");
}
this.resolvedDataSources = new HashMap<Object, DataSource>(this.targetDataSources.size());
for (Map.Entry<Object, Object> entry : this.targetDataSources.entrySet()) {
Object lookupKey = resolveSpecifiedLookupKey(entry.getKey());
DataSource dataSource = resolveSpecifiedDataSource(entry.getValue());
this.resolvedDataSources.put(lookupKey, dataSource);
}
if (this.defaultTargetDataSource != null) {
this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);
}
}
这个方法是通过targetDataSources对resolvedDataSources进行赋值的。targetDataSources我们可以用过配置文件进行配置,这样就可以设置当前使用哪个数据库了,但是需要先要准备一下前提条件。
第一步:我们先要重写上面的determineCurrentLookupKey方法,我们新建一个创建一个DynamicDataSource的类,用来获取自定义获取数据源的标识(和当前线程中使用的数据源):
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource { @Override
protected Object determineCurrentLookupKey() {
// 从自定义的位置获取数据源标识
return DynamicDataSourceHolder.getDataSource();
} }
第二步:创建DynamicDataSourceHolder类用于切换要操作的数据源,代码如下:
package com.dingdao.apiserver.utils; public class DynamicDataSourceHolder
{
private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal(); public static String getDataSource()
{
return (String)THREAD_DATA_SOURCE.get();
} public static void setDataSource(String dataSource)
{
THREAD_DATA_SOURCE.set(dataSource);
} public static void clearDataSource()
{
THREAD_DATA_SOURCE.remove();
}
}
到这里我们的前期的准备工作已经做完了,下面将我的配置文件粘贴出来:
jdbc.properties:
driverClasss =com.mysql.jdbc.Driver(笔者用的mysql,如果不是mysql请自行替换)
jdbcUrl=jdbc:第一个数据库的链接
username=第一个数据库的用户名
password=第一个数据库的密码
jrt_driverClasss=com.mysql.jdbc.Driver(笔可以直接调用第一个的driverClasss,笔者只是用于看着舒服,啊哈哈)
jrt_jdbcUrl=jdbc:第二个数据库的链接
jrt_username=第二个数据库的用户名
jrt_password=第二个数据库的密码
#定义初始连接数
initialSize=0
#定义最大连接数
maxActive=20
#定义最大空闲
maxIdle=20
#定义最小空闲
minIdle=1
#定义最长等待时间
maxWait=60000
spring-mybatis.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 自动扫描 -->
<context:component-scan base-package="com.dingdao.apiserver.*"/> <!-- 第一种方式:加载一个properties文件 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
</bean> <!-- 配置第一个数据源 -->
<bean id="defultdataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${driverClasss}"/>
<property name="url" value="${jdbcUrl}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<!-- 初始化连接大小 -->
<property name="initialSize" value="${initialSize}"></property>
<!-- 连接池最大数量 -->
<property name="maxActive" value="${maxActive}"></property>
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="${maxIdle}"></property>
<!-- 连接池最小空闲 -->
<property name="minIdle" value="${minIdle}"></property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="${maxWait}"></property>
</bean> <!-- 配置第二个数据源 -->
<bean id="jrt_dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jrt_driverClasss}"/>
<property name="url" value="${jrt_jdbcUrl}"/>
<property name="username" value="${jrt_username}"/>
<property name="password" value="${jrt_password}"/>
<!-- 初始化连接大小 -->
<property name="initialSize" value="${initialSize}"></property>
<!-- 连接池最大数量 -->
<property name="maxActive" value="${maxActive}"></property>
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="${maxIdle}"></property>
<!-- 连接池最小空闲 -->
<property name="minIdle" value="${minIdle}"></property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="${maxWait}"></property>
</bean> <bean id="dataSource" class="com.dingdao.apiserver.utils.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<!-- 指定lookupKey和与之对应的数据源,这里的key可以自行定义,要切换数据库的时候以key为标识,不要写错 -->
<entry key="defultdataSource" value-ref="defultdataSource"></entry>
<entry key="jrt_dataSource" value-ref="jrt_dataSource"></entry>
</map>
</property>
<!-- 这里可以指定默认的数据源 -->
<property name="defaultTargetDataSource" ref="defultdataSource" />
</bean> <!-- mybatis和spring完美整合,不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 自动扫描mapping.xml文件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
</bean> <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dingdao.apiserver.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean> <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean> <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<tx:annotation-driven transaction-manager="transactionManager"/> </beans>
使用默认数据库的时候可以什么都不用写,但是切换为非默认数据库的时候就要进行设置了,下面把调用两种数据库的方法贴出来:
使用默认数据库的service的实现类代码:
@Autowired
@Qualifier("nitceDao")
NitceDao nitceDao; public Map<String, Object> getNotice(Map<String, Object> map) {
List<Map<String, Object>> notice = nitceDao.getNotice(map);
Map<String,Object> maps = new HashMap<String, Object>();
maps.put("lists", notice);
return maps;
}
不适用默认数据库service的实现类代码:
@Autowired
@Qualifier("testJRTDao")
private TestJRTDao testJRTDao; public String AllColor() {
DynamicDataSourceHolder.setDataSource("jrt_dataSource");
JSONObject jsonObject = new JSONObject();
List<Map<String ,Object>> list = testJRTDao.selectAllColor();
jsonObject.put("AllColor",list);
return jsonObject.toString();
}
到这里两个数据库的切换已经可以实现了。
SSM项目实现连接两个mysql数据库的更多相关文章
- Windows安装两个mysql数据库步骤
因为新旧项目数据库版本号差距太大.编码格式不同.引擎也不同,所以仅仅好装两个数据库. 本次安装两个mysql数据库.版本号各自是4.0.18,5.5.36.都是可运行文件直接安装. 本机上之前已经安装 ...
- 两台Mysql数据库数据同步实现
两台Mysql数据库数据同步实现 做开发的时候要做Mysql的数据库同步,两台安装一样的系统,都是FreeBSD5.4,安装了Apache 2.0.55和PHP 4.4.0,Mysql的版本是4.1. ...
- R语言使用RMySQL连接及读写Mysql数据库 测试通过
R语言使用RMySQL连接及读写Mysql数据库 简单说下安装过程,一般不会有问题,重点是RMySQL的使用方式. 系统环境说明 Redhat系统:Linux 460-42.6.32-431.29.2 ...
- linux下程序JDBC连接不到mysql数据库
今天在linux下部署一个 JavaEE项目的时候总是连接不到Mysql数据库,检查之后发现连接池的配置确定是对的,进入linux服务器之后以mysql -uname -ppassword连接总是报A ...
- JAVA连接SqlServer2008R2和MySql数据库
问题描述: 下面是有关连接SqlServer2008R2和MySql数据库的封装类 package com.test; import java.sql.Connection; import java. ...
- 寝室远程连接室友mysql数据库
注意,本方法是适用于同一局域网下的远程连接 注意,本方法是适用于同一局域网下的远程连接 注意,本方法是适用于同一局域网下的远程连接 首先需要修改mysql数据库的相关配置,将user表中的host改为 ...
- robot_framewok自动化测试--(9)连接并操作 MySql 数据库
连接并操作 MySql 数据库 1.mysql数据库 1.1安装mysql数据库 请参考我的另一篇文章:MYSQL5.7下载安装图文教程 1.2.准备测试数据 请参考我的另一篇文章:Mysql基础教程 ...
- Spring Boot项目中MyBatis连接DB2和MySQL数据库返回结果中一些字符消失——debug笔记
写这篇记录的原因是因为我之前在Spring Boot项目中通过MyBatis连接DB2返回的结果中存在一些字段, 这些字段的元素中缺少了一些符号,所以我现在通过在自己的电脑上通过MyBatis连接DB ...
- SQL多表连接查询以及mysql数据库、sqlserver数据库常见不同点
mysql数据库表及数据准备语句: USE test; DROP TABLE IF EXISTS `teacher_table`; DROP TABLE IF EXISTS `student_tabl ...
随机推荐
- Linux下core文件调试
1,ulimit -a查看默认参数 2,ulimit -c 1024 设置core文件大小,如果超过1024个blocks,则不会产生core文件 注:tune2fs -l /dev/sda8 输出分 ...
- Redis事务,持久化,哨兵机制
1 Redis事务 基本事务指令 Redis提供了一定的事务支持,可以保证一组操作原子执行不被打断,但是如果执行中出现错误,事务不能回滚,Redis未提供回滚支持. multi 开启事务 exec 执 ...
- MySQL中查询所有数据库占用磁盘空间大小
查询所有数据库占用磁盘空间大小的SQL语句: 复制代码 代码如下:select TABLE_SCHEMA, concat(truncate(sum(data_length)/1024/1024,2), ...
- 简单的GridView分业,后台不需要写
1前台代码: <asp:GridView ID="GridView1" runat="server" AllowPaging="True&quo ...
- PHP-SQL查询上升的温度
给定一个 Weather 表,编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 Id. +---------+------------------+------------- ...
- js获取当前网址Url
js获取当前路径并截取 var str = window.location.href;// str = 'https://localhost:8080/mark' var index = str .l ...
- jquery实现文字由下到上循环滚动的实例代码
<div id="oDiv"> <ul id="oUl"> <li>第1个li元素</li> <li> ...
- 解决 php Call to undefined function shm_attach()
学习php 多进程的时候,运行脚本报错 Call to undefined function shm_attach() ,搜了一下,看到stack overflow 里面提示需要配置这些扩展 exte ...
- oracle将查询结果横转纵
SELECT '残疾人|民政|综合治理|计划生育|物业监管|安全生产|环境类|司法信访|党建|社会组织|文化体育|社保' D , '53|52|51|50|49|48|47|5|4|3|2|1' g ...
- C++Builder中注册表的操作
僮骶头浅5募虻チ耍旅嫖揖鸵砸桓鍪道此得鱐Registry类的用法.首先,先介绍一下TRegistry的属性和方法:TRegistry类一共有四个属性.属性 类型 描述CurrentKey int ...