⼀个Web项⽬实现多个数据库存储数据并相互切换
1、使⽤场景
多数据源使⽤场景⼀般为:
1. 主从数据库切换
2. 读写分离
3. 兼容旧库
2、具体实现
实现原理
Spring2.x的版本中采⽤Proxy模式,就是在⽅案中实现⼀个虚拟的数据源,并且⽤它来封装数据源选择逻辑,这样就可以有效地将数据源选择逻辑从Client中分离出来。Client提供选择所需的上下⽂,由虚拟的DynamicDataSource根据Client提供的上下⽂来实现数据源的选择。
具体的实现是创建⼀个名为DynamicDataSource的类仅需继承AbstractRoutingDataSource实现determine
CurrentLookupKey(),该⽅法返回需要使⽤的DataSource的key值,然后根据这个key从resolvedDataSources这个map⾥取出对应的DataSource,如果不到则⽤默认的resolvedDefaultDataSource。
具体实现过程
1.修改jdbcConfig.properties数据源配置⽂件为⼀下内容(具体数据源可⾃⾏修改)
# A 数据库源A
jdbc.a.driver = sql.cj.jdbc.Driver
jdbc.a.url = jdbc:mysql://localhost:3306/test1?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
jdbc.a.username = root
jdbc.a.password = 123456
# B 数据库源B
jdbc.b.driver = sql.cj.jdbc.Driver
jdbc.b.url = jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
jdbc.b.username = root
jdbc.b.password = 123456
2.修改l配置⽂件,需要配置多个数据源,修改后配置如下
<!-- 引⼊jdbc配置⽂件 -->
<context:property-placeholder location="classpath:jdbcConfig.properties"></context:property-placeholder>
<!--    spring 整合 mybatis-->
<!-- 1.配置数据源 C3P0 1 -->
<bean id="dataSourceTargetA" class="hange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.a.driver}"/>
<property name="jdbcUrl" value="${jdbc.a.url}"/>
<property name="user" value="${jdbc.a.username}"/>
<property name="password" value="${jdbc.a.password}"/>
</bean>
<!-- 配置数据源 C3P0 2 -->
<bean id="dataSourceTargetB" class="hange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.b.driver}"/>
<property name="jdbcUrl" value="${jdbc.b.url}"/>
<property name="user" value="${jdbc.b.username}"/>
<property name="password" value="${jdbc.b.password}"/>
</bean>
<!--  动态数据源  -->
<bean id="dataSource" class="com.hk.handler.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="dataSourceTargetA" key="dataSourceTargetA"></entry>
<entry value-ref="dataSourceTargetB" key="dataSourceTargetB"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSourceTargetA"></property>
</bean>
<!--  2.配置SqlSessionFactory⼯⼚  -->
<bean id="sessionFactory" class="batis.spring.SqlSessionFactoryBean">
<!--  注⼊数据源    -->
<property name="dataSource" ref="dataSource"/>
<!--    实体类起别名    -->
<property name="typeAliasesPackage" value="del"></property>
<!--  指定mapper接⼝所对应的xml-->
<property name="mapperLocations" value="classpath:com/hk/mapper/*.xml"></property>
<!-- 指定Mybatis的核⼼配置⽂件 -->
<property name="configLocation" value="l"></property>
</bean>
<!--    3.配置接⼝AccountDao所在的包映射扫描配置类 mvc配置 -->
<bean id="mapperScanner" class="batis.spring.mapper.MapperScannerConfigurer">
<!--    接⼝所在的包    -->
<property name="basePackage" value="com.hk.mapper"/>
<!--    扫描⼯⼚并注⼊sqlSessionFactoryBeanName  -->
<property name="sqlSessionFactoryBeanName" value="sessionFactory"/>
</bean>
<!-- 配置spring声明式事务管理  -->
<!--  配置事务管理器  -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--  传⼊连接池对象      -->
<property name="dataSource" ref="dataSource"/>
</bean>
3.创建动态数据源管理类
DynamicDataSource类继承AbstractRoutingDataSource,实现determineCurrentLookupKey()⽅法。
/**
* @Author: aerfazhe
* @Date: 2021/6/26 10:00
* @Statement: 数据源切换类
*/
public class CustomerContextHolder {
public static final String DATA_SOURCE_DEFAULT = "dataSourceTargetA";
public static final String DATA_SOURCE_B = "dataSourceTargetB";
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setCustomerType(String customerType) {
contextHolder.set(customerType);springframework事务
}
public static String getCustomerType() {
();
}
public static void clearCustomerType() {
}
}
5.使⽤多数据源代码
以Controller层代码为演⽰,需要添加信息到B数据源,完成后切换到A数据源进⾏查询,具体代码如下
@PostMapping("/save")
public String save(User user) {
CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_B);
int save = iuserService.save(user);
CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_DEFAULT);
if (save == 1) {
return "success";
}
return "error";
}
@GetMapping("/findAll")
@ResponseBody
public Map<String,Object> findAll() {
List<User> userList = iuserService.findAll();
Map<String,Object> map = new HashMap<>();
map.put("status",0);
map.put("msg","success");
map.put("list",userList);
return map;
}
先从数据库B中的表进⾏添加数据,添加完成后,会切换到默认的数据库A,然后再从数据库A中的表查询数据,这样就达到了在⼀个Web项⽬中,根据不⽤的模块和业务需求,实现多个数据库存储数据和它们之间的切换了。
如有任何问题,欢迎评论区留⾔,希望可以帮助到⼤家。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。