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 ...
随机推荐
- icmp隧道--icmpsh
本地:ubantu 目标主机:windows 在ubantu上关闭自带的icmp回应 sysctl -w net.ipv4.icmp_echo_ighore_all=1 ubantu上启动 pip i ...
- 流计算与Hadoop
- Java 基础 - CLASSPATH 到底是什么
关于JAVA项目中CLASSPATH路径详解 https://www.cnblogs.com/hibou/p/8324276.html java项目中的classpath到底是什么 https://s ...
- [JZOJ4331] 【清华集训模拟】树
题目 题目大意 给你一棵带点权的树,求将树变成一堆不相交的链,而且这些链的权值和非负的方案数. 正解 显然这道题是个\(DP\). 首先求个前缀和\(sum\). 为了后面讲述方便,我这样设:\(f_ ...
- Open CV 环境配置
{ //https://github.com/zhmmmm/ANYTOOL-2.0.0.0.2Version/tree/master/OpenCVProject } /* //各个版本下载 https ...
- 双线程DP
1.传纸条 好像是一道普及组水题? //Twenty #include<cstdio> #include<iostream> #include<cstring> # ...
- vue.js+web storm安装及第一个vue.js
小白还是自己写一遍吧 1.下载node.js https://nodejs.org/en/download/ 2.安装淘宝镜像(类似于阿里云的maven中央仓库镜像) 安装时间有点长 安装命令:npm ...
- hexo next主题深度优化(十),博文加密,不需要插件,极简模式,相对安全,融合pjax。
文章目录 效果: 代码: 注意: 背景: 思路: https://www.jianshu.com/p/90c0a15c6f36 http://zhailiange.com/2017/07/06/hex ...
- STM32笔记——Power Controller(PWR)
The device requires a 1.8 to 3.6 V operating voltage supply (VDD). An embedded linear voltage regula ...
- ie9 jscript7 内存不足 页面无响应
花了我差不多一天时间 我是加载一个datagrid ,多表联查,查询几遍(不一定,又是1遍就死了)后 就卡死了...后台日志都是过的.... 后来我发现数据库某个表的数据很多有一模一样的两条,把一份删 ...