- 浏览: 340448 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (212)
- spring (21)
- design pattern(java) (12)
- linux-shell (28)
- java-thread (20)
- java-collection (6)
- java-reflect (9)
- mysql (11)
- java-io (7)
- java-util&lang&io (3)
- algorithm (3)
- interview (2)
- tools-eclipse (2)
- tools-maven (1)
- web-script (1)
- java组建 (13)
- 博客收藏 (1)
- 架构设计与实践 (10)
- active-mq (6)
- java-jvm&性能&原理 (27)
- tomcat (2)
- flume (1)
- serialization (2)
- git (1)
- cache&redis (8)
- guava (1)
- zookeeper (3)
- socket&tcp&udp&http (6)
- test (1)
最新评论
-
bbls:
有用有用有用
java-jvm-jstack-(监视器和锁的概念) -
王新春:
小侠有点帅哦 写道此流怎么关闭新春这个实现 可以不关闭的,哈哈 ...
源码剖析之java.io.ByteArrayOutputStream -
小侠有点帅哦:
此流怎么关闭新春
源码剖析之java.io.ByteArrayOutputStream -
cumt168:
写的很好为什么初始化参数,年轻代-Xmn10M def new ...
jvm之内存申请过程分析 -
ronin47:
应该是跟共享域名思路差不多,根据cookie的key作判断
跨域:一种通过服务端解决跨域的实现
spring jdbc 提供了抽象类AbstractRoutingDataSource,来提供切换多数据源功能
应对场景:在一个项目中要与多个数据库打交道,尤其大项目,更要考虑垂直切分业务,以存储数据到不同的库。
spring 基于jdbc 的 DataSource ,提供了对选择数据库做路由切换的功能。
案例:下面的案例很好的实现了一个巧妙切库的功能,思路简单明了,另外很好的结合了spring aop的功能,使用方便简洁。
需求:
1、数据库common 库,存储了通用信息,仅有一个通用库。
2、代理商库customer库。每个代理商存储各自的独立信息,有多个代理商库。
现在我们要写一个IClientShardDao 来取common 库一个表中的数据和一个ILoginLogDao 来取customer 库中一个表的数据。
分析与实现:
1、DAO层,我们定义统一的JdbcTemplate 来操作数据,但对其的dataSource 的配置,采用 AbstractRoutingDataSource 的一个实现 DBRoutingDataSource来实现,而DBRoutingDataSource 又根据 DBContext 来确定当前操作的应该是那个dataSource ,DBContext 是一个 通过ThreadLocal 来实现的线程上下文安全的实例。
2、DBContext 信息的设置,可以考虑结合Spring AOP。对不同的DAO 操纵不同的库,可以手动设置DBContext,很灵活,但是AOP可以更规范也更方便简洁的在方法调用的前设定数据库的相关信息。
配置和代码:
1、数据源的配置(applicationContext-datasource.xml)。
2、spring 启动的配置和扫描包
jdbc.properties 的内容:
3、DBRoutingDataSource 的实现。
4、DBContext 的信息。
5、 AOP对DBContext 的dbkey的设置。
6、具体dao的实现。
详细代码见附件~
多个templete 会很乱的,现在统一了,更方便
多个template或一个template都可以实现多数据源,只不过多个来的更直观而已,用选择方法进行选择调用就可以。
你这个DBRoutingDataSource里面关闭connection连Finally都没用,也没有用现成的Spring的Connection管理方法,连接池的选用也有问题,还用了aop拦截降低代码执行效率,dao的具体实现也是硬编码,最关键的多数据源的事务处理也没有提到,你这篇文章基本上讲是一无是处,完全没用。
希望你把基本功学扎实了,把Spring和JdbcTemplate相关的方法源代码都看了再考虑这些“发明创造”的事情。
1、DBRoutingDataSource 里的 connection 需要关闭吗?
2、连接池的选用也有问题:什么问题,请指教!
3、aop拦截降低代码执行效率: 有些项目 可以在效率和便捷性之间做妥协的吧,我不认为aop拦截相对于数据库连接会有很大的性能问题,当然你可以这么认为。
4、dao的具体实现也是硬编码 :dao的实现是case,例子本身就是case,没有打算面面具到。
5、这篇文章基本上讲是一无是处:谢谢你.
6、希望你把基本功学扎实了,把Spring和JdbcTemplate相关的方法源代码都看了再考虑这些“发明创造”的事情:谢谢你,没有创造,只是把工作中实际项目中的用法拿出来分享思路,没有必要面面俱到。
不要理这个人,估计心情不好
多个templete 会很乱的,现在统一了,更方便
多个template或一个template都可以实现多数据源,只不过多个来的更直观而已,用选择方法进行选择调用就可以。
你这个DBRoutingDataSource里面关闭connection连Finally都没用,也没有用现成的Spring的Connection管理方法,连接池的选用也有问题,还用了aop拦截降低代码执行效率,dao的具体实现也是硬编码,最关键的多数据源的事务处理也没有提到,你这篇文章基本上讲是一无是处,完全没用。
希望你把基本功学扎实了,把Spring和JdbcTemplate相关的方法源代码都看了再考虑这些“发明创造”的事情。
1、DBRoutingDataSource 里的 connection 需要关闭吗?
2、连接池的选用也有问题:什么问题,请指教!
3、aop拦截降低代码执行效率: 有些项目 可以在效率和便捷性之间做妥协的吧,我不认为aop拦截相对于数据库连接会有很大的性能问题,当然你可以这么认为。
4、dao的具体实现也是硬编码 :dao的实现是case,例子本身就是case,没有打算面面具到。
5、这篇文章基本上讲是一无是处:谢谢你.
6、希望你把基本功学扎实了,把Spring和JdbcTemplate相关的方法源代码都看了再考虑这些“发明创造”的事情:谢谢你,没有创造,只是把工作中实际项目中的用法拿出来分享思路,没有必要面面俱到。
多个templete 会很乱的,现在统一了,更方便
多个template或一个template都可以实现多数据源,只不过多个来的更直观而已,用选择方法进行选择调用就可以。
你这个DBRoutingDataSource里面关闭connection连Finally都没用,也没有用现成的Spring的Connection管理方法,连接池的选用也有问题,还用了aop拦截降低代码执行效率,dao的具体实现也是硬编码,最关键的多数据源的事务处理也没有提到,你这篇文章基本上讲是一无是处,完全没用。
希望你把基本功学扎实了,把Spring和JdbcTemplate相关的方法源代码都看了再考虑这些“发明创造”的事情。
多个templete 会很乱的,现在统一了,更方便
应对场景:在一个项目中要与多个数据库打交道,尤其大项目,更要考虑垂直切分业务,以存储数据到不同的库。
spring 基于jdbc 的 DataSource ,提供了对选择数据库做路由切换的功能。
案例:下面的案例很好的实现了一个巧妙切库的功能,思路简单明了,另外很好的结合了spring aop的功能,使用方便简洁。
需求:
1、数据库common 库,存储了通用信息,仅有一个通用库。
2、代理商库customer库。每个代理商存储各自的独立信息,有多个代理商库。
现在我们要写一个IClientShardDao 来取common 库一个表中的数据和一个ILoginLogDao 来取customer 库中一个表的数据。
分析与实现:
1、DAO层,我们定义统一的JdbcTemplate 来操作数据,但对其的dataSource 的配置,采用 AbstractRoutingDataSource 的一个实现 DBRoutingDataSource来实现,而DBRoutingDataSource 又根据 DBContext 来确定当前操作的应该是那个dataSource ,DBContext 是一个 通过ThreadLocal 来实现的线程上下文安全的实例。
2、DBContext 信息的设置,可以考虑结合Spring AOP。对不同的DAO 操纵不同的库,可以手动设置DBContext,很灵活,但是AOP可以更规范也更方便简洁的在方法调用的前设定数据库的相关信息。
配置和代码:
1、数据源的配置(applicationContext-datasource.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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="parentDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" abstract="true"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 每隔毫秒秒检查一次连接池中空闲的连接 --> <property name="minEvictableIdleTimeMillis" value="600000" /> <!-- 连接池中连接可空闲的时间,毫秒 --> <property name="removeAbandoned" value="true" /> <!-- 是否清理removeAbandonedTimeout秒没有使用的活动连接,清理后并没有放回连接池 --> <property name="removeAbandonedTimeout" value="60" /> <!-- 活动连接的最大空闲时间 --> <property name="minIdle" value="10" /> <!-- 最小空闲连接数 --> <property name="maxWait" value="60000" /> <!-- 最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间 --> </bean> <!-- common库的数据源 -- > <bean id="comDataSource" parent="parentDataSource"> <property name="url" value="${jdbc.com.url}" /> <property name="username" value="${jdbc.com.username}" /> <property name="password" value="${jdbc.com.password}" /> </bean> <!-- customer库的数据源--> <bean id="cusDataSource" parent="parentDataSource"> <property name="url" value="${jdbc.cus.url}" /> <property name="username" value="${jdbc.cus.username}" /> <property name="password" value="${jdbc.cus.password}" /> </bean> <!-- 配置路由切换数据源 --> <bean id="dataSource" class="com.job.db.dbswitch.DBRoutingDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="${jdbc.com.key}" value-ref="comDataSource" /> <entry key="${jdbc.cus.key}" value-ref="cusDataSource" /> </map> </property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg ref="dataSource"/> </bean> <!-- 启动AOP --> <aop:aspectj-autoproxy/> </beans>
2、spring 启动的配置和扫描包
<context:property-placeholder location="classpath*:*.properties" /> <context:component-scan base-package="com.job.service, com.job.dao,com.job.db" /> <import resource="applicationContext-datasource.xml"/>
jdbc.properties 的内容:
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.com.key=com jdbc.com.url=jdbc:mysql://comip:3306/db?useUnicode=true&characterEncoding=utf8 jdbc.com.username=comuser jdbc.com.password=compassword jdbc.cus.key=cus jdbc.cus.url=jdbc:mysql://cusip:3306/?useUnicode=true&characterEncoding=utf8 jdbc.cus.username=cususer jdbc.cus.password=cuspassword
3、DBRoutingDataSource 的实现。
package com.job.db.dbswitch; import java.sql.Connection; import java.sql.SQLException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; import com.job.vo.ClientShard; /** * @author wangxinchun1988@163.com * @date 2014-7-11下午4:47:09 */ public class DBRoutingDataSource extends AbstractRoutingDataSource { private static Logger log = LoggerFactory.getLogger(DBRoutingDataSource.class); public boolean isWrapperFor(Class arg0) throws SQLException { return false; } public Object unwrap(Class arg0) throws SQLException { return null; } public Object determineCurrentLookupKey() { return DBContext.getDBKey(); } @Override public Connection getConnection() throws SQLException{ Connection con = super.getConnection(); changeUser(con); return con; } @Override public Connection getConnection(String username, String password) throws SQLException{ Connection con = super.getConnection(username, password); changeUser(con); return con; } /** * 重要,在MYSQLD中使用use xxx切换数据库。 */ private void changeUser(Connection con) { ClientShard cs = DBContext.getCust(); if (DBContext.getDBKey()!=null && !DBContext.getDBKey().equals("com")){ if (DBContext.getCust().getId()!=null){ try { con.createStatement().execute("use `"+DBContext.getCust().getDatabaseName()+"`"); } catch (SQLException e) { log.error("change db error!!! {}", cs, e); e.printStackTrace(); try { if(con!=null&&!con.isClosed()){ con.close(); } } catch (SQLException e1) { log.error("close db error {}", cs, e1); } } } } } public java.util.logging.Logger getParentLogger() { return null; } }
4、DBContext 的信息。
package com.job.db.dbswitch; import com.job.vo.ClientShard; public class DBContext { private static final ThreadLocal<String> DBKeyl = new ThreadLocal<String>(); private static final ThreadLocal<ClientShard> custDBl = new ThreadLocal<ClientShard>(); public static String getDBKey(){ return DBKeyl.get(); } public static void setDBKey(String dbKey){ DBKeyl.set(dbKey); } public static void clearDBKey(){ DBKeyl.remove(); } public static void setCust(ClientShard cust){ custDBl.set(cust); } public static ClientShard getCust(){ return custDBl.get(); } public static void releaseAll(){ DBKeyl.remove(); custDBl.remove(); } }
5、 AOP对DBContext 的dbkey的设置。
package com.job.db.dbswitch; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; /** * DbSwitchAop * @author wangxinchun1988@163.com * @date 2014-7-11下午12:02:30 */ @Aspect @Component public class DbSwitchAop { // 使用common数据库 @Before("target(com.job.db.dbmark.ICommonDBMark)") public void commonMethodBefore() { DBContext.setDBKey("com"); } // 使用customer数据库 @Before("target(com.job.db.dbmark.ICustomerDBMark)") public void customerDaoMethodBefore() { DBContext.setDBKey("cus"); } }
package com.job.db.dbmark; /** * 通用db(单库) * @author wangxinchun1988@163.com * @date 2014-7-10下午7:59:23 */ public interface ICommonDBMark { }
/** * 自定义db(多库) * @author wangxinchun1988@163.com * @date 2014-7-10下午7:59:11 */ public interface ICustomerDBMark { }
6、具体dao的实现。
package com.job.dao; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; import com.job.db.dbmark.ICustomerDBMark; import com.job.db.dbswitch.DBContext; import com.job.vo.ClientShard; import com.job.vo.LoginLog; /** * 关键是对ICustomerDBMark 的实现,使其具有方法调用前,对DBContext设置相关dbkey信息 * @author wangxinchun1988@163.com * @date 2014-7-11下午5:23:38 */ @Repository public class LoginLogDaoImpl implements ILoginLogDao,ICustomerDBMark{ @Autowired private JdbcTemplate jdbcTemplate; public List<LoginLog> getLoginLogList(ClientShard shard) { String sql = "SELECT id, username, ip, login_time as loginTime FROM login_log limit 1"; DBContext.setCust(shard); List<LoginLog> retList = jdbcTemplate.query(sql, new RowMapper<LoginLog>(){ public LoginLog mapRow(ResultSet rs, int rowNum) throws SQLException { LoginLog item = new LoginLog(); item.setId(rs.getLong("id")); item.setUsername(rs.getString("username")); item.setIp(rs.getString("ip")); item.setLoginTime(rs.getDate("loginTime")); return item; } }); System.out.println(retList); return retList; } }
/** * 对ICommonDBMark接口的实现非常重要,这是aop对DBContxt设置dbkey的途径 * @author wangxinchun1988@163.com * @date 2014-7-11下午5:24:53 */ @Repository public class ClientShardDaoImpl implements IClientShardDao,ICommonDBMark { @Autowired private JdbcTemplate jdbcTemplate; public List<ClientShard> queryDataList() { DBContext.setDBKey("com"); String sql = "select id,host,port,databaseName,clientId,config,order_prefix as orderPrefix from client_shard limit 10"; List<ClientShard> dataList = jdbcTemplate.query(sql, new RowMapper<ClientShard>(){ public ClientShard mapRow(ResultSet rs, int rowNum) throws SQLException { ClientShard item = new ClientShard(); item.setId(rs.getLong("id")); item.setClientId(rs.getString("clientId")); item.setOrderPrefix(rs.getString("orderPrefix")); item.setDatabaseName(rs.getString("databaseName")); return item ; } }); System.out.println(dataList); return dataList; } }
详细代码见附件~
- spring-learning-jdbc.rar (1.7 MB)
- 下载次数: 64
评论
6 楼
wxyvgo
2014-08-28
写的不错,借鉴了!
正好有类型的需求要实现。
正好有类型的需求要实现。
5 楼
yunzhu
2014-07-23
王新春 写道
evanzzy 写道
王新春 写道
evanzzy 写道
往基类Dao里面多注入几个数据源不就好了么,怎么写这么多
多个templete 会很乱的,现在统一了,更方便
多个template或一个template都可以实现多数据源,只不过多个来的更直观而已,用选择方法进行选择调用就可以。
你这个DBRoutingDataSource里面关闭connection连Finally都没用,也没有用现成的Spring的Connection管理方法,连接池的选用也有问题,还用了aop拦截降低代码执行效率,dao的具体实现也是硬编码,最关键的多数据源的事务处理也没有提到,你这篇文章基本上讲是一无是处,完全没用。
希望你把基本功学扎实了,把Spring和JdbcTemplate相关的方法源代码都看了再考虑这些“发明创造”的事情。
1、DBRoutingDataSource 里的 connection 需要关闭吗?
2、连接池的选用也有问题:什么问题,请指教!
3、aop拦截降低代码执行效率: 有些项目 可以在效率和便捷性之间做妥协的吧,我不认为aop拦截相对于数据库连接会有很大的性能问题,当然你可以这么认为。
4、dao的具体实现也是硬编码 :dao的实现是case,例子本身就是case,没有打算面面具到。
5、这篇文章基本上讲是一无是处:谢谢你.
6、希望你把基本功学扎实了,把Spring和JdbcTemplate相关的方法源代码都看了再考虑这些“发明创造”的事情:谢谢你,没有创造,只是把工作中实际项目中的用法拿出来分享思路,没有必要面面俱到。
不要理这个人,估计心情不好
4 楼
王新春
2014-07-12
evanzzy 写道
王新春 写道
evanzzy 写道
往基类Dao里面多注入几个数据源不就好了么,怎么写这么多
多个templete 会很乱的,现在统一了,更方便
多个template或一个template都可以实现多数据源,只不过多个来的更直观而已,用选择方法进行选择调用就可以。
你这个DBRoutingDataSource里面关闭connection连Finally都没用,也没有用现成的Spring的Connection管理方法,连接池的选用也有问题,还用了aop拦截降低代码执行效率,dao的具体实现也是硬编码,最关键的多数据源的事务处理也没有提到,你这篇文章基本上讲是一无是处,完全没用。
希望你把基本功学扎实了,把Spring和JdbcTemplate相关的方法源代码都看了再考虑这些“发明创造”的事情。
1、DBRoutingDataSource 里的 connection 需要关闭吗?
2、连接池的选用也有问题:什么问题,请指教!
3、aop拦截降低代码执行效率: 有些项目 可以在效率和便捷性之间做妥协的吧,我不认为aop拦截相对于数据库连接会有很大的性能问题,当然你可以这么认为。
4、dao的具体实现也是硬编码 :dao的实现是case,例子本身就是case,没有打算面面具到。
5、这篇文章基本上讲是一无是处:谢谢你.
6、希望你把基本功学扎实了,把Spring和JdbcTemplate相关的方法源代码都看了再考虑这些“发明创造”的事情:谢谢你,没有创造,只是把工作中实际项目中的用法拿出来分享思路,没有必要面面俱到。
3 楼
evanzzy
2014-07-12
王新春 写道
evanzzy 写道
往基类Dao里面多注入几个数据源不就好了么,怎么写这么多
多个templete 会很乱的,现在统一了,更方便
多个template或一个template都可以实现多数据源,只不过多个来的更直观而已,用选择方法进行选择调用就可以。
你这个DBRoutingDataSource里面关闭connection连Finally都没用,也没有用现成的Spring的Connection管理方法,连接池的选用也有问题,还用了aop拦截降低代码执行效率,dao的具体实现也是硬编码,最关键的多数据源的事务处理也没有提到,你这篇文章基本上讲是一无是处,完全没用。
希望你把基本功学扎实了,把Spring和JdbcTemplate相关的方法源代码都看了再考虑这些“发明创造”的事情。
2 楼
王新春
2014-07-12
evanzzy 写道
往基类Dao里面多注入几个数据源不就好了么,怎么写这么多
多个templete 会很乱的,现在统一了,更方便
1 楼
evanzzy
2014-07-12
往基类Dao里面多注入几个数据源不就好了么,怎么写这么多
发表评论
-
mvc-HandlerMapping
2017-06-03 23:13 835HandlerMapping:定义了web请求映射和处 ... -
spring-transaction-basic
2016-12-26 19:18 402Spring的事务本身是基于AOP的 AOP代理自 ... -
spring-transaction-propagation
2016-11-25 21:00 847Spring 事务:是spring 通过 aop实现的一套 ... -
spring bean & id
2016-11-25 17:57 454首先澄清一个概念: 同名bean:多个bean ... -
spring 父子容器
2016-11-25 17:11 3639特殊说明: ContextLoaderListe ... -
spring-mvc-基础
2016-09-26 15:03 387核心入口功能定位: HttpServletBean:完成的是& ... -
spring-mvc 学习资料
2016-09-20 15:42 351http://docs.spring.io/spring-fr ... -
spring-aop-DefaultAdvisorAutoProxyCreator
2016-08-16 19:50 463ProxyFactory:手工编程实现AOP,编程式 添加ad ... -
spring-aop基本概念
2016-07-26 16:37 822AOP词汇: Joinpoint:在程序执行过程中某个特定的 ... -
spring-扩展点-BeanFactoryPostProcessor
2016-06-15 18:15 6003BeanFactoryPostProcessor:允许自定 ... -
spring-扩展点-BeanPostProcessor
2016-06-14 15:02 1553理解spring中一个bean的初始化过程非常重要,很多基础功 ... -
spring-扩展点-namespacehandler(Spring自定义标签)
2016-05-27 11:31 2207在很多情况下,我们需要为系统提供可配置化支持,简单的做法可以直 ... -
spring 资源文件
2015-04-03 00:07 148【转载】 非原创 SpringMVC访问静态资源的三种方式 ... -
spring-master-slave-commondao
2014-07-19 14:32 2240互联网的web项目,都有个特点:请求的并发量高,其中请求最耗时 ... -
spring-aop-ProxyFactoryBean 源码分析
2014-06-13 19:10 2029在阅读本篇之前,请先阅读http://wangxinchun. ... -
spring-aop-ProxyFactory 源码分析
2014-06-13 02:22 4772spring 提供的编程式aop实现,即通过 ProxyFac ... -
spring-aop-aspectj(Schema)-case
2014-05-31 15:50 1085基于Schema 配置切面: 1、切点定义的语言依然是Aspe ... -
spring-aop-aspectj-case
2014-05-31 14:51 1363AOP概念:面向切面编程。 spring 集成AOP: 1、 ... -
spring-rpc-case
2014-05-17 23:34 1087spring 提供了基本的基于http协议的rpc,同时提供了 ... -
spring-mvc-case
2014-05-10 23:50 1190spring mvc 是当前java比较流行的一种mvc架构, ...
相关推荐
`spring-boot-starter-jdbc`和`spring-boot-starter-data-jpa`等启动器是实现多数据源的关键依赖,它们包含了连接池、JDBC和JPA等组件。 综上所述,Spring Boot 2.0多数据源功能允许开发者灵活地管理和切换多个...
在Spring框架中,配置多数据源JDBC是一项常见的任务,特别是在构建分布式系统或者需要处理多个数据库的应用中。这里我们将深入探讨如何在Spring中实现这一功能,以及涉及的相关知识点。 首先,我们要理解数据源...
Spring提供了`org.springframework.jdbc.datasource.DriverManagerDataSource`类,可以直接通过Java代码配置。但在实际项目中,通常我们会使用XML或Java配置来创建一个Bean,如下所示: ```xml ...
然而,当我们需要动态数据源时,需要引入额外的库,如`spring-boot-starter-jdbc`和`spring-boot-starter-aop`,这两个库分别用于JDBC支持和面向切面编程(AOP),这是实现动态数据源的关键组件。 接下来,我们需要...
<bean id="transactionManagerSecondary" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <bean id="dynamicTransactionManager" class="org.springframework.jdbc.datasource....
Spring 框架结合 MyBatis 持久层框架,提供了灵活的数据源配置方案,使得我们可以根据业务需求切换或同时操作不同的数据库。下面将详细介绍如何在 Spring 和 MyBatis 配置中实现多数据源。 首先,我们需要准备两个...
spring.datasource.dataSource1.url=jdbc:mysql://localhost:3306/db1 spring.datasource.dataSource1.username=root spring.datasource.dataSource1.password=root spring.datasource.dataSource2.url=jdbc:mysql:...
<bean id="routingDataSource" class="org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource"> <map key-type="java.lang.String"> <entry key="primary" value-ref="dataSource"/> ...
数据源(DataSource)是一个接口,它是Java的JDBC API的一部分,用于存储数据库连接信息并管理与数据库的连接。在Spring中,我们可以使用如Apache Commons DBCP或HikariCP等第三方库来实现数据源。 Spring动态数据...
在Spring中,我们可以使用`org.springframework.jdbc.datasource.DriverManagerDataSource`或`com.zaxxer.hikari.HikariDataSource`等来创建数据源。 配置多数据源时,我们通常会使用Spring的`...
- 实现`RoutingDataSource`接口,重写`determineCurrentLookupKey()`方法,根据上下文中的数据源标识符来决定使用哪个数据源。 ```java @Configuration public class DynamicDataSource extends ...
1. **配置多个数据源**:在Spring的配置文件中,为每个数据库创建一个DataSource bean,例如`dataSource1`和`dataSource2`,并配置相应的JDBC连接信息。 2. **数据源路由**:引入Spring的AbstractRoutingDataSource...
Spring框架提供了一种强大的机制来支持多数据源的配置与动态切换,帮助开发者解决这一问题。本文将详细阐述如何在Spring中创建、配置以及动态地切换多数据源。 首先,我们需要理解什么是多数据源。简单来说,多数据...
spring.datasource.url=jdbc:mysql://localhost:3306/datasource1 spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver ``` 在多数据源...
首先,我们需要创建一个自定义的`RoutingDataSource`,并实现`determineCurrentLookupKey`方法来确定当前的数据源: ```java @Configuration public class DynamicDataSourceConfig { @Autowired private Map, ...
spring.datasource.primary.url=jdbc:mysql://localhost:3306/master_db spring.datasource.primary.username=root spring.datasource.primary.password=root spring.datasource.primary.driver-class-name=...
spring.datasource.db1.url=jdbc:mysql://localhost:3306/db1 spring.datasource.db1.username=root spring.datasource.db1.password=password spring.datasource.db1.driver-class-name=com.mysql.jdbc.Driver ...
spring.datasource.primary.url=jdbc:mysql://localhost:3306/db1 spring.datasource.primary.username=root spring.datasource.primary.password=root spring.datasource.primary.driver-class-name=...
routingDataSource.setTargetDataSources(Maps.newHashMap(DataSourceNames.MASTER, masterDataSource(), DataSourceNames.SLAVE, slave1DataSource())); routingDataSource.setDefaultTargetDataSource...