在applicationContent.xml中:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config/jdbc.properties</value>
<value>classpath:config/cpool.properties</value>
</list>
</property>
</bean>
<!-- 主数据源 -->
<bean id="masterDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.masterDriverClass}" />
<property name="jdbcUrl" value="${jdbc.masterUrl}" />
<property name="user" value="${jdbc.masterUsername}" />
<property name="password" value="${jdbc.masterPassword}" />
<property name="checkoutTimeout" value="${cpool.checkoutTimeout}" />
<property name="initialPoolSize" value="${cpool.initialPoolSize}" />
<property name="minPoolSize" value="${cpool.minPoolSize}" />
<property name="maxPoolSize" value="${cpool.maxPoolSize}" />
<property name="maxIdleTime" value="${cpool.maxIdleTime}" />
<property name="acquireIncrement" value="${cpool.acquireIncrement}" />
<property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}" />
</bean>
<!-- 从数据源 -->
<bean id="slaveDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.slaveDriverClass}" />
<property name="jdbcUrl" value="${jdbc.slaveUrl}" />
<property name="user" value="${jdbc.slaveUsername}" />
<property name="password" value="${jdbc.slavePassword}" />
<property name="checkoutTimeout" value="${cpool.checkoutTimeout}" />
<property name="initialPoolSize" value="${cpool.initialPoolSize}" />
<property name="minPoolSize" value="${cpool.minPoolSize}" />
<property name="maxPoolSize" value="${cpool.maxPoolSize}" />
<property name="maxIdleTime" value="${cpool.maxIdleTime}" />
<property name="acquireIncrement" value="${cpool.acquireIncrement}" />
<property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}" />
</bean>
<!-- 动态切换数据源 -->
<bean id="dataSource" class="com.xxx.xxx.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="slave" value-ref="slaveDataSource" />
<entry key="master" value-ref="masterDataSource" />
</map>
</property>
<property name="defaultTargetDataSource" ref="masterDataSource" />
</bean>
<!-- 配置事务的传播特性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception" />
<tx:method name="*" read-only="true" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
<!-- 动态切换数据源的切面 -->
<bean id="dataSourceAdvice" class="com.xxx.xxx.DataSourceAdvice" />
<!-- 那些类的哪些方法参与事务 -->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* *..service*..*(..))" />
<aop:advisor order="-2147483648" pointcut-ref="txPointcut" advice-ref="dataSourceAdvice" /> <!-- 数据源主从切换(顺序要在事务上面) -->
<aop:advisor pointcut-ref="txPointcut" advice-ref="txAdvice" /><!-- 事务 -->
</aop:config>
Java类:
/** 数据源动态切换类 */
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceSwitcher.getDataSource();
}
}
/** 数据源转换器 */
public class DataSourceSwitcher {
private static final ThreadLocal contextHolder = new ThreadLocal();
@SuppressWarnings("unchecked")
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static void setMaster() {
setDataSource("master");
}
public static void setSlave() {
setDataSource("slave");
}
public static String getDataSource() {
return (String) contextHolder.get();
}
}
/** 数据源判断切面 */
public class DataSourceAdvice implements MethodBeforeAdvice, ThrowsAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
if (method.getName().startsWith("add") || method.getName().startsWith("create") || method.getName().startsWith("save") || method.getName().startsWith("edit") || method.getName().startsWith("update") || method.getName().startsWith("delete") || method.getName().startsWith("remove")) {
DataSourceSwitcher.setMaster();
} else {
DataSourceSwitcher.setSlave();
}
}
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
System.out.println("异常切换到: master");
DataSourceSwitcher.setMaster();
}
}
分享到:
相关推荐
本文将深入探讨如何在SpringBoot项目中配置多数据源,并实现数据源的动态切换,帮助你理解和掌握这一核心技能。 首先,我们理解"多数据源"的概念。在SpringBoot应用中,多数据源意味着系统能够连接并操作多个不同的...
在Spring Boot应用中,数据源切换是一个常见的需求,特别是在分布式系统或者微服务架构中,可能需要连接多个数据库来实现不同的业务功能。本示例“spring boot数据源切换demo”将展示如何在Spring Boot中集成MyBatis...
创建一个自定义的数据源切换注解,比如`@SwitchDataSource`,并在需要切换数据源的方法上使用。通过AspectJ的切面处理,我们可以在方法执行前后动态改变ThreadLocal中的数据源引用。 3. **Spring Cloud Config ...
本文将详细讨论如何使用Spring Boot、MyBatis和Druid来实现MySQL与Hive之间的多数据源切换,以满足不同业务场景的需求。 首先,Spring Boot是Spring框架的一种轻量级实现,它简化了配置并提供了快速开发新应用的...
综上所述,"spring+druid+AtomikosDataSource"的组合为开发者提供了一套强大的工具,用于实现多数据源切换和分布式事务控制。在实际项目中,通过合理的配置和编码,可以构建出高效、健壮的分布式系统。在`mult-table...
通过以上步骤,我们就实现了MyBatis与Spring配合下的动态数据源切换。这种机制有助于在多租户系统、读写分离或者高可用架构中灵活地管理数据库访问,提高了系统的可扩展性和灵活性。在实际应用中,还需要考虑数据源...
本教程将详细阐述如何在Spring Boot项目中实现这一功能,从数据源配置、实体管理到Mapper和Controller的整合。 一、配置多数据源 1. 引入依赖 首先,我们需要在`pom.xml`或`build.gradle`文件中添加相应的Spring ...
Spring可以通过XML配置或Java配置来实现多数据源。Java配置更符合现代开发习惯,也更易于理解和维护。 3. **核心组件**: - `AbstractRoutingDataSource`:这是Spring提供的核心类,用于动态路由数据源。它会根据...
综上所述,通过上述关键知识点的实施,可以在Spring Boot应用中成功配置和实现多数据源动态切换的功能。这一功能的实现,不仅可以提高数据库操作的灵活性和性能,还可以使得数据库的管理更加清晰和高效。
在本文中,我们将深入探讨如何实现动态数据源切换,支持Spring声明式事务管理,并讨论多数据源回滚策略。以下是对这些知识点的详细说明: 1. **动态数据源切换**: - 通过AspectJ实现数据源的动态切换,可以设置在...
2. **数据源切换**:通过`@Profile`注解实现不同环境下的数据源选择。在Spring Boot中,可以通过配置文件(如application.properties或application.yml)指定当前环境,然后在数据源配置类上使用`@Profile`注解,使...
使用注解配置实现Spring动态数据源切换,实现原理 1、自定义动态数据源类DynamicDataSource: 实现spring类AbstractRoutingDataSource的方法determineCurrentLookupKey 2、自定义Spring AOP类DataSourceAspect 3、...
- 在生产环境中,需要确保数据源切换的正确性,可以使用监控工具(如Spring Actuator)跟踪数据源切换情况,同时编写单元测试和集成测试确保功能正常。 综上所述,Spring动态切换数据源是通过配置不同数据源,结合...
- AOP切面的Java类,实现了方法执行前后的拦截和数据源切换。 - 数据源相关的Java配置类,用于配置Spring的DataSource和MybatisPlus。 - Mapper接口和对应的XML文件,定义数据库操作。 - 业务逻辑层的Java类,其中的...
在企业级应用开发中,Spring框架的广泛使用使得...通过这种方式,我们可以灵活地处理复杂的数据源切换场景,适应不同业务的需求。在实际项目中,还需要考虑线程安全、异常处理、测试等方面的问题,确保系统稳定运行。
在多数据源配置中,Spring能够帮助管理不同的数据源,通过配置bean来切换和控制数据源的使用。 **SpringMVC** 是Spring框架的一部分,专为Web开发设计。它简化了模型-视图-控制器(Model-View-Controller,MVC)的...
Spring提供了多种方式来管理多数据源,例如通过`AbstractRoutingDataSource`实现动态数据源切换。这个类可以根据某些条件(如事务的标识、请求上下文等)动态决定使用哪个数据源。在`dynamicDatasourceDemo`项目中,...
在实际项目中,你可能还需要配置事务管理器,如`PlatformTransactionManager`,以及根据业务需求调整数据源切换策略。同时,为了提高代码的可读性和可维护性,可以考虑使用AOP(面向切面编程)或自定义注解来简化...
在Spring Boot应用中,整合MyBatis和Druid并实现多数据源切换是一项常见的需求,尤其是在处理多个数据库环境(如开发、测试、生产)时。本文将深入探讨如何配置和使用这一技术栈。 首先,我们需要了解`spring boot`...
在Spring框架中,通过配置和编程方式可以方便地实现这一功能。 SSI(Singleton Service Interface,单例服务接口)是一种设计模式,它确保在整个应用中,对某个服务的访问都是通过同一个实例来进行,以此实现资源的...