Java书签 #使用MyBatis接入多数据源

楔子:当然,世上有很多优秀的女性,我也会被她们吸引。这对男人来说是理所当然的。但目光被吸引和内心被吸引是截然不同的。- 东野圭吾《黎明之街》

1.今日书签

在一些应用场景中,可能需要连接多个不同的数据库,例如连接不同的数据库服务器或者连接主从数据库。这段代码就是为了实现这种多数据源的配置。

具体来说,这个类包含两个内部静态类:

  1. MyBatisDataSourceConfiguration4XMei: 这个类配置了第一个数据源,即 “xmei” 数据源。它使用了
    @Primary 注解来指示这是默认的主数据源。这个数据源配置了一个 Druid 数据源,并配置了与该数据源相关的
    SqlSessionFactory、事务管理器(DataSourceTransactionManager)和
    SqlSessionTemplate。@MapperScan 注解用于指示需要扫描哪些包下的 Mapper 接口,并使用特定的
    SqlSessionFactory。它还定义了 Mapper XML 文件的路径,以及事务管理和 SqlSessionTemplate。
  2. MyBatisDataSourceConfiguration4XWei: 这个类配置了第二个数据源,即 “xwei” 数据源。它没有使用
    @Primary 注解,因此不是默认的主数据源。它使用了 @Qualifier 注解来指定特定的 Bean
    名称,用于解决多个数据源的冲突。与第一个数据源类似,它配置了一个 Druid 数据源,并定义了与该数据源相关的
    SqlSessionFactory、事务管理器和 SqlSessionTemplate。

 

2.多数据源

使用 Service、Mapper、XML 所在包路径区分默认数据源 与 第二数据源。
直接看代码:

/**
 * 多数据源接入
 * dataSource4XMei 为 xmei 库,为默认数据源,正常使用,此处以外无其它配置
 * dataSource4XWei 为 xwei 库,为第二数据源,正常使用,此处以外无其它配置
 */
@Configuration
public class MyBatisConfiguration {

    /**
     * 配置 SpringBoot 默认数据源,一般配置为主数据库,此为 xmei
     */
    @Configuration
    @MapperScan(basePackages = {"com.cw.tan.xmei.persistence.*"}, sqlSessionFactoryRef = "sqlSessionFactory4XMei")
    protected static class MyBatisDataSourceConfiguration4XMei {
        @Bean
        @Primary
        @ConfigurationProperties("spring.datasource.druid.xmei")
        public DataSource dataSource4XMei() {
            return DruidDataSourceBuilder.create().build();
        }

        @Bean
        @Primary
        public SqlSessionFactory sqlSessionFactory4XMei(DataSource dataSource4XMei) throws Exception {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource4XMei);
            sqlSessionFactoryBean.setMapperLocations(this.resolveMapperLocations());
            return sqlSessionFactoryBean.getObject();
        }

        private Resource[] resolveMapperLocations() {
            ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
            List<String> mapperLocations = new ArrayList<>();
            mapperLocations.add("classpath*:com/cw/tan/xmei/persistence/**/*.xml");
            List<Resource> resources = new ArrayList();
            if (!CollectionUtils.isEmpty(mapperLocations)) {
                for (String mapperLocation : mapperLocations) {
                    try {
                        Resource[] mappers = resourceResolver.getResources(mapperLocation);
                        resources.addAll(Arrays.asList(mappers));
                    } catch (IOException e) {
                        // ignore
                    }
                }
            }
            return resources.toArray(new Resource[resources.size()]);
        }

        /**
         * 配置事务管理
         */
        @Bean
        @Primary
        public DataSourceTransactionManager transactionManager4XMei(DataSource dataSource4XMei) {
            return new DataSourceTransactionManager(dataSource4XMei);
        }

        @Bean
        @Primary
        public SqlSessionTemplate sqlSessionTemplate4XMei(SqlSessionFactory sqlSessionFactory4XMei) {
            return new SqlSessionTemplate(sqlSessionFactory4XMei);
        }
    }

    /**
     * 配置第二数据源,注意 mapper 扫描路径和上面的区分开
     */
    @Configuration
    @MapperScan(basePackages = {"com.cw.tan.xwei.log.mapper","com.cw.tan.xwei.sms.mapper", "com.cw.tan.xwei.job.mapper"}, sqlSessionFactoryRef = "sqlSessionFactory4XWei")
    protected static class MyBatisDataSourceConfiguration4XWei {

        @Bean(name = "dataSource4XWei")
        @ConfigurationProperties("spring.datasource.druid.xwei")
        public DataSource dataSource4XWei() {
            return DruidDataSourceBuilder.create().build();
        }

        @Bean(name = "sqlSessionFactory4XWei")
        public SqlSessionFactory sqlSessionFactory4XWei(@Qualifier("dataSource4XWei") DataSource dataSource4XWei) throws Exception {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource4XWei);
            sqlSessionFactoryBean.setMapperLocations(this.resolveMapperLocations());
            return sqlSessionFactoryBean.getObject();
        }

        private Resource[] resolveMapperLocations() {
            ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
            List<String> mapperLocations = new ArrayList<>();
            mapperLocations.add("classpath*:com/cw/tan/xwei/log/**/*.xml");
            mapperLocations.add("classpath*:com/cw/tan/xwei/sms/**/*.xml");
            mapperLocations.add("classpath*:com/cw/tan/xwei/job/**/*.xml");
            List<Resource> resources = new ArrayList<>();
            if (!CollectionUtils.isEmpty(mapperLocations)) {
                mapperLocations.forEach(mapperLocation -> {
                    try {
                        Resource[] mappers = resourcePatternResolver.getResources(mapperLocation);
                        resources.addAll(Arrays.asList(mappers));
                    } catch (IOException e) {
                        // ignore
                    }
                });
            }

            return resources.toArray(new Resource[resources.size()]);
        }

        @Bean(name = "transactionManager4XWei")
        public DataSourceTransactionManager transactionManager4XWei(@Qualifier("dataSource4XWei") DataSource dataSource4XWei) {
            return new DataSourceTransactionManager(dataSource4XWei);
        }

        @Bean(name = "sqlSessionTemplate4XWei")
        public SqlSessionTemplate sqlSessionTemplate4XWei(@Qualifier("sqlSessionFactory4XWei") SqlSessionFactory sqlSessionFactory4XWei) {
            return new SqlSessionTemplate(sqlSessionFactory4XWei);
        }
    }
}

注意:上述配置,请确认自己的默认数据源、第二数据源对应Service、DAO文件所在的包路径,如果路径指向不对,可能会出现以下异常:
2023-08-17 16:09:33.981 [TID:] [main] WARN AnnotationConfigServletWebServerApplicationContext.refresh():559 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘dataDataSyncController’: Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.cw.tan.xwei.job.IDataSyncService’ available: expected single matching bean but found 2: dataSyncServiceImpl,IDataSyncService

 

3.配置中心

druid 配置

第一数据源,即 “xmei” 数据源的 Apollo 配置:

spring.datasource.druid.xmei.url = jdbc:mysql://mysql.test.cw.com:3306/xmei?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true&rewriteBatchedStatements=true&useSSL=false
spring.datasource.druid.xmei.username = xmei
spring.datasource.druid.xmei.password = 12345678
spring.datasource.druid.xmei.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.druid.xmei.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.xmei.defaultAutoCommit = true
spring.datasource.druid.xmei.initialSize = 10
spring.datasource.druid.xmei.minIdle = 10
spring.datasource.druid.xmei.maxActive = 50
spring.datasource.druid.xmei.maxWait = 1000
spring.datasource.druid.xmei.validationQuery = SELECT 1
spring.datasource.druid.xmei.testWhileIdle = true
spring.datasource.druid.xmei.testOnBorrow = true
spring.datasource.druid.xmei.testOnReturn = false
spring.datasource.druid.xmei.filters = config,stat,wall
spring.datasource.druid.xmei.filter.stat.slow-sql-millis = 1000

第一数据源,即 “xwei” 数据源的 Apollo 配置:

spring.datasource.druid.xwei.url = jdbc:mysql://mysql.test.cw.com:3306/xwei?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true&rewriteBatchedStatements=true&useSSL=false
spring.datasource.druid.xwei.username = bi_hs
spring.datasource.druid.xwei.password = d41d8cd98f00b204
spring.datasource.druid.xwei.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.druid.xwei.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.xwei.defaultAutoCommit = true
spring.datasource.druid.xwei.initialSize = 10
spring.datasource.druid.xwei.minIdle = 10
spring.datasource.druid.xwei.maxActive = 50
spring.datasource.druid.xwei.maxWait = 1000
spring.datasource.druid.xwei.validationQuery = SELECT 1
spring.datasource.druid.xwei.testWhileIdle = true
spring.datasource.druid.xwei.testOnBorrow = true
spring.datasource.druid.xwei.testOnReturn = false
spring.datasource.druid.xwei.filters = config,stat,wall
spring.datasource.druid.xwei.filter.stat.slow-sql-millis = 1000

application.yml 配置

spring:
  application:
    name: x-cw
  profiles:
    active: test

apollo:
  bootstrap:
    enabled: true
    namespaces: application.yml,redis.yml,db_xmei.properties,db_xwei.properties

 

4.总结

这段代码通过两个内部静态类分别配置了两个不同的数据源(xmei 和 xwei)。每个数据源配置了对应的 Druid 数据源、SqlSessionFactory、事务管理器和 SqlSessionTemplate。这种多数据源配置适用于需要访问多个不同数据库的场景,如在一个系统中同时连接多个数据库来进行不同的操作,比如主数据库和日志数据库、数据库与业务库数据同步等。

如果还需要扩展更多数据源,则可将上述 第二数据源配置 进行复制粘贴,然后做相应名称、包路径的修改,再加上第N数据源配置即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java项目中,通过MyBatis实现多数据实例可以按照以下步骤进行: 1. 在项目中引入MyBatis数据库驱动。 2. 在项目中定义多个数据,对应不同的数据库。可以使用Spring框架的`DataSource`接口实现类来定义数据。 3. 配置MyBatis的SqlSessionFactory,指定多个数据。 4. 在Mapper接口中使用`@MapperScan`注解指定要扫描的Mapper接口路径。 5. 在Mapper.xml文件中,使用`<selectKey>`标签指定使用数据。 示例代码如下: ``` //定义数据1 @Bean @ConfigurationProperties(prefix = "spring.datasource.db1") public DataSource dataSource1() { return DataSourceBuilder.create().build(); } //定义数据2 @Bean @ConfigurationProperties(prefix = "spring.datasource.db2") public DataSource dataSource2() { return DataSourceBuilder.create().build(); } //配置MyBatis的SqlSessionFactory,指定多个数据 @Bean public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource1") DataSource dataSource1, @Qualifier("dataSource2") DataSource dataSource2) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource1); //设置Mapper.xml文件路径 Resource[] mapperLocations = new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/*.xml"); sqlSessionFactoryBean.setMapperLocations(mapperLocations); //设置多个数据 Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put("dataSource1", dataSource1); targetDataSources.put("dataSource2", dataSource2); DynamicDataSource dataSource = new DynamicDataSource(); dataSource.setTargetDataSources(targetDataSources); dataSource.setDefaultTargetDataSource(dataSource1); sqlSessionFactoryBean.setDataSource(dataSource); return sqlSessionFactoryBean.getObject(); } //在Mapper.xml文件中,使用<selectKey>标签指定使用数据 <select id="getUserInfoById" resultMap="userInfo" > <selectKey resultType="java.lang.Integer" order="BEFORE" keyProperty="dataSource"> SELECT CASE WHEN id < 1000 THEN &#39;dataSource1&#39; ELSE &#39;dataSource2&#39; END AS dataSource FROM user_info WHERE id = #{id} </selectKey> SELECT * FROM user_info WHERE id = #{id} </select> ``` 其中,我们使用了`DynamicDataSource`类来实现动态数据的切换。在`DynamicDataSource`类中,我们需要重写`determineCurrentLookupKey()`方法,根据具体的业务场景来动态切换数据。 ``` public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } } ``` 最后,我们需要在业务代码中设置数据的类型,以实现动态切换数据。 ``` public class UserServiceImpl implements UserService { @Override public UserInfo getUserInfoById(Integer id) { DataSourceContextHolder.setDataSourceType("dataSource1"); UserInfo userInfo = userMapper.getUserInfoById(id); return userInfo; } } ``` 以上就是通过MyBatis实现多数据实例的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值