应开发需求需要,根据项目业务,不同业务下的数据存入不同的数据库中,且须读写分离。目前常用的有两种方式:
第一种:定义多个个数据库连接,分别是AReadDataSource,AWriteDataSource,BReadDataSource,BWriteDataSource,CReadDataSource, CWriteDataSource来实现;
第二种:动态数据源切换,就是在程序运行时,把数据源动态织入到程序中,从而选择读取对应的数据库。主要使用的技术是:annotation,Spring AOP ,反射。具体实现方式如下:
先定义一个annotation的注解类:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface DataSourceNote { String dbSource() default ""; }
添加一个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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- testA读库写库 start --> <bean id="testAReadDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- 读库个性化配置 --> <property name="driverClassName" value="${jdbc.testA_read.driver}"/> <property name="url" value="${jdbc.testA_read.url}"/> <property name="username" value="${jdbc.testA_read.username}"/> <property name="password" value="${jdbc.testA_read.password}"/> </bean> <bean id="testAWriteDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- 写库个性化配置 --> <property name="driverClassName" value="${jdbc.testA_write.driver}"/> <property name="url" value="${jdbc.testA_write.url}"/> <property name="username" value="${jdbc.testA_write.username}"/> <property name="password" value="${jdbc.testA_write.password}"/> </bean> <!-- testA读库写库 end --> <!-- testB读库写库 start --> <bean id="testBReadDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- 读库个性化配置 --> <property name="driverClassName" value="${jdbc.testB_read.driver}"/> <property name="url" value="${jdbc.testB_read.url}"/> <property name="username" value="${jdbc.testB_read.username}"/> <property name="password" value="${jdbc.testB_read.password}"/> </bean> <bean id="testBWriteDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- 写库个性化配置 --> <property name="driverClassName" value="${jdbc.testB_write.driver}"/> <property name="url" value="${jdbc.testB_write.url}"/> <property name="username" value="${jdbc.testB_write.username}"/> <property name="password" value="${jdbc.testB_write.password}"/> </bean> <!-- testB读库写库 end --> <!-- testC读库 写库 start --> <bean id="testCReadDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- 读库个性化配置 --> <property name="driverClassName" value="${jdbc.testC_read.driver}"/> <property name="url" value="${jdbc.testC_read.url}"/> <property name="username" value="${jdbc.testC_read.username}"/> <property name="password" value="${jdbc.testC_read.password}"/> </bean> <bean id="testCWriteDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- 写库个性化配置 --> <property name="driverClassName" value="${jdbc.testC_write.driver}"/> <property name="url" value="${jdbc.testC_write.url}"/> <property name="username" value="${jdbc.testC_write.username}"/> <property name="password" value="${jdbc.testC_write.password}"/> </bean> <!-- testC读库 写库 end --> <bean id="dataSource" class="com.test.dao.aspect.ChooseDataSource" lazy-init="true"> <description>数据源</description> <property name="targetDataSources"> <map key-type="java.lang.String" value-type="javax.sql.DataSource"> <!-- write --> <entry key="testAWrite" value-ref="testAWriteDataSource" /> <entry key="testBWrite" value-ref="testBWriteDataSource" /> <entry key="testCWrite" value-ref="testCWriteDataSource" /> <!-- read --> <entry key="testARead" value-ref="testAReadDataSource" /> <entry key="testBRead" value-ref="testBReadDataSource" /> <entry key="testCRead" value-ref="testCReadDataSource" /> </map> </property> <property name="methodType"> <map key-type="java.lang.String"> <!-- read --> <entry key="testARead" value=",get,select,count,list,query," /> <entry key="testBRead" value=",get,select,count,list,query," /> <entry key="testCRead" value=",get,select,count,list,query," /> <!-- write --> <entry key="testAWrite" value=",add,insert,create,update,delete,remove," /> <entry key="testBWrite" value=",add,insert,create,update,delete,remove," /> <entry key="testCWrite" value=",add,insert,create,update,delete,remove," /> </map> </property> </bean> <!-- 切面 --> <bean class="com.test.dao.aspect.DataSourceAspect" /> <!-- jdbc模板 --> <bean class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg ref="dataSource" /> </bean> </beans>
然后将dataSource.xml配置到spring-config.xml里面去,具体参考如下文件:
<import resource="classpath*:spring/dataSource.xml"/>
mybatis.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd"> <!-- 开启注解配置 --> <context:annotation-config /> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" /> <!-- 自动扫描mapping.xml文件 --> <property name="mapperLocations" value="classpath:sqlmaps/**/*.xml" /> </bean> <!-- 事务管理 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> </beans>
现在再来看看,dataSource.xml里面相关的两个类的代码,第一个DataSourceAspect,用于动态切换数据库源:
@Aspect @EnableAspectJAutoProxy(proxyTargetClass = true) @Log4j2 public class DataSourceAspect { @Pointcut("execution(* com.test.dao.*..*Impl.*(..))") public void aspect() { } /** * 配置前置通知,使用在方法aspect()上注册的切入点 */ @Before("aspect()") public void before(JoinPoint point) { String method = point.getSignature().getName(); Log4j2Util.printLog4j2(log,this, method, Level.INFO, "(" + StringUtils.join(point.getArgs(), ",") + ")"); //获取到对象的类 Object obj = point.getTarget(); Method methods[] = obj.getClass().getMethods(); for (int i = 0; i< methods.length; i++) { if(method.equals(methods[i].getName())){ DataSourceNote note = methods[i].getAnnotation(DataSourceNote.class); String dbSource = note.dbSource(); if(StringUtils.isNotEmpty(dbSource)){ Log4j2Util.printLog4j2(log,this, "before", Level.DEBUG, "---------数据库类型:"+dbSource); HandleDataSource.putDataSource(dbSource); }else{ Log4j2Util.printLog4j2(log,this, "before", Level.ERROR, "---------数据库类型:"+dbSource); } } } } @After("aspect()") public void after(JoinPoint point) { HandleDataSource.clear(); } }
下面再来看看ChooseDataSource类的处理,获取对应的dataSource里面的数据源:
public class ChooseDataSource extends AbstractRoutingDataSource { public static Map<String, List<String>> METHODTYPE = new HashMap<String, List<String>>(); // 获取数据源名称 protected Object determineCurrentLookupKey() { return HandleDataSource.getDataSource(); } // 设置方法名前缀对应的数据源 public void setMethodType(Map<String, String> map) { for (String key : map.keySet()) { List<String> v = new ArrayList<String>(); String[] types = map.get(key).split(","); for (String type : types) { if (StringUtils.isNotBlank(type)) { v.add(type); } } METHODTYPE.put(key, v); } } }
代码实际使用示例如下:
public class TestDataDaoImpl extends BaseDao implements TestDataDao{ private static final String NAME_SPACE = "com.test.dao.TestDataDao."; @Override @DataSourceNote(dbSource = "testAWrite") public boolean addTestAUserMsg(List<UserDO> list) throws DaoException { Integer count = this.insert(NAME_SPACE + "addTestAUserMsg", list); return (count == null || count == 0) ? false : true; } @Override @DataSourceNote(dbSource = "testBWrite") public boolean addTestBUserMsgLog(List<UserMsgLogDO> list) throws DaoException { Integer count = this.insert(NAME_SPACE + "addTestBUserMsgLog", list); return (count == null || count == 0) ? false : true; } @Override @DataSourceNote(dbSource = "testCRead") public UserDetail queryTestCUserDetail(Map<String, String> param) throws DaoException { UserDetail temp = (UserDetail ) this.queryForObject(NAME_SPACE + "queryTestCUserDetail", param); return temp; } }
按步骤依顺配置下来即可,不是很明白的地方可以去看看org.apache.commons.dbcp.BasicDataSource里的createConnectionFactory方法。及其他相关方法
相关推荐
当我们面临多数据源的配置需求时,即在一个应用程序中需要同时操作多个数据库,Spring和Mybatis的集成就显得尤为重要。这篇博客“Spring+Mybatis 多数据源配置”将深入探讨如何在项目中实现这一功能。 首先,我们...
总之,Spring+MyBatis多数据源配置是大型项目中常见的需求,它通过`AbstractRoutingDataSource`实现了动态数据源选择,结合MyBatis的Mapper接口和注解,可以方便地在多个数据库之间切换,从而满足复杂的数据库访问...
在多数据源配置中,Spring能够帮助管理不同的数据源,通过配置bean来切换和控制数据源的使用。 **SpringMVC** 是Spring框架的一部分,专为Web开发设计。它简化了模型-视图-控制器(Model-View-Controller,MVC)的...
在多数据源场景下,我们可以通过Spring Boot的@ConfigurationProperties特性来配置不同的数据源。每个数据源都需要定义一套包括URL、用户名、密码和驱动类名等属性。例如: ```java @Configuration @...
总结,Spring Boot结合Mybatis和Druid实现多数据源配置的过程包括:配置数据源、配置Mybatis、创建数据源切换器、以及针对不同数据库的测试。这一过程涉及了Spring Boot的自动配置、依赖注入、配置属性绑定等多个...
然后配置Spring的applicationContext.xml,包括Bean定义、AOP配置、数据源、事务管理器等。接着配置Spring MVC的servlet-context.xml,设置DispatcherServlet、视图解析器、拦截器等。最后,配置MyBatis的mybatis-...
- MyBatis的配置文件(mybatis-config.xml)中,设置数据源和SqlSessionFactory,以便MyBatis与数据库交互。 通过以上步骤,我们可以构建一个松耦合、可测试的系统,每个组件都发挥着它应有的作用,而注解方式的...
1. **配置文件**:包括Spring的bean配置文件(如`applicationContext.xml`)和MyBatis的配置文件(如`mybatis-config.xml`),它们定义了数据源、事务管理器、SqlSessionFactory以及Mapper接口的扫描路径。...
3. **配置MyBatis**:编写MyBatis的配置文件,包括数据源、SqlSessionFactory,并为每个Mapper接口定义XML映射文件。 4. **整合Spring和Struts2**:使用Spring的Struts2插件,使Spring管理的Bean可以直接在Struts2 ...
总结来说,"Spring+SpringMVC+Mybatis多数据源"的整合涉及了Spring的数据源管理、SpringMVC的请求路由、Mybatis的数据源配置以及事务管理。具体实现时,可以根据项目需求选择合适的方式进行数据源切换,以达到优化...
在多数据源环境中,MyBatis的配置文件需要包含多个数据源的信息,每次操作数据库时,可以通过SqlSessionFactoryBuilder创建指定数据源的SqlSessionFactory,然后通过SqlSession来执行SQL。 项目的...
5. **MyBatis配置**:在多数据源环境下,MyBatis的配置需要针对每个数据源分别设置SqlSessionFactory,并在Mapper接口上通过@MapperScan注解指定对应的SqlSessionFactory。 6. **事务管理**:在多数据源情况下,...
本项目结合了SpringBoot、Gradle和MyBatis,旨在实现多数据源的动态配置,这对于处理多个数据库或者分库分表的场景尤其有用。以下是对这个项目的详细解析: **SpringBoot** SpringBoot是由Pivotal团队提供的全新...
Spring Boot通过`@EnableAutoConfiguration`注解自动配置了大量常见服务,包括数据源和MyBatis的配置。然而,当涉及到多个数据源时,我们需要手动进行一些配置。 1. **配置双数据源** - 首先,为每个数据源创建一...
对于MyBatis,我们需要创建`mybatis-config.xml`配置文件,配置数据源、事务管理器以及映射文件的位置。 数据库方面,本系统使用了MySQL,通过MyBatis的SqlSessionFactory和SqlSession对象,我们可以执行SQL语句。`...
标题中的"struts+spring+mybatis源代码例子"意味着这是一个实际的项目示例,包含了这三个框架的集成使用,可以帮助开发者理解和学习如何在实际项目中整合这些技术。通过分析和研究这个源代码,开发者可以深入理解...
在实际项目中,开发者通常会创建一个配置文件(如:`springmvc_mybatis1208`可能包含的`spring-config.xml`),在其中配置Spring和MyBatis的相关设置,包括数据源、事务管理器、SqlSessionFactory等。同时,还需要...
4. 配置MyBatis:编写mybatis-config.xml,包含数据源、事务管理器、环境等信息。 5. 配置Mapper:创建Mapper接口和对应的XML文件,定义SQL语句。 6. 配置Spring与MyBatis的集成:使用MyBatis-Spring的...
- **src/main/resources**:存放配置文件,如Spring的bean配置、Mybatis的Mapper XML文件、数据库连接配置等。 - **webapp**:Web应用目录,其中`WEB-INF`下存放web.xml,定义了Servlet和Filter等Web组件;`jsp`...