Spring Boot下配置MyBatis多数据源

Spring Boot最大的特点是简化开发,因此使用Java Config实现去xml配置,本文将使用这种方式完成对阿里云ADS和RDS两个产品的多数据源配置。同时,会用到阿里巴巴的开源数据源Druid。

依赖

  • 因为ADS和RDS都兼容mysql的JDBC实现,因此工程只需要依赖mysql的driver。
  • Spring Boot易用性的特点是通过Starter实现的,我们只需依赖mybatis的spring-boot-starter即可。
  • Druid是数据源。
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>${mybatis-spring-boot-starter.version}</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>${druid.version}</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql-connector-java.version}</version>
</dependency>
<properties>
    <mysql-connector-java.version>5.1.34</mysql-connector-java.version>
    <druid.version>1.0.18</druid.version>
    <mybatis-spring-boot-starter.version>1.1.1</mybatis-spring-boot-starter.version>
</properties>

数据源配置

多数据源配置要求必须有一个是『主』,我们将RDS设定为主,配置如下:

@Configuration
@MapperScan(basePackages = RdsDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "rdsSqlSessionFactory")
public class RdsDataSourceConfig {
    static final String PACKAGE = "com.aliyun.xxx.repository.mybatis.rds";

    @Value("${xxx_mysql_url}")
    private String dbUrl;
    @Value("${xxx_mysql_username}")
    private String dbUser;
    @Value("${xxx_mysql_password}")
    private String dbPassword;

    @Bean(name = "rdsDataSource")
    @Primary
    public DataSource rdsDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl(dbUrl);
        dataSource.setUsername(dbUser);
        dataSource.setPassword(dbPassword);
        return dataSource;
    }

    @Bean(name = "rdsTransactionManager")
    @Primary
    public DataSourceTransactionManager rdsTransactionManager() {
        return new DataSourceTransactionManager(rdsDataSource());
    }

    @Bean(name = "rdsSqlSessionFactory")
    @Primary
    public SqlSessionFactory rdsSqlSessionFactory(@Qualifier("rdsDataSource") DataSource rdsDataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(rdsDataSource);
        return sessionFactory.getObject();
    }
}
  • @Value将获取Spring Boot全局配置文件的kv配置。也可以通过Environment对象的getProperty方法获得kv配置。
  • @MapperScan配置要扫描并容器管理的包路径,这里我们精确到rds,以便使其内的Mapper(见下文)与其他数据源隔离。
  • sqlSessionFactoryRef要定义key唯一的SqlSessionFactory实例,否则同名的处理是后者被忽略。

类似地,另一个数据源ADS的配置如下:

@Configuration
@MapperScan(basePackages = AdsDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "adsSqlSessionFactory")
public class AdsDataSourceConfig {
    static final String PACKAGE = "com.aliyun.xxx.repository.mybatis.ads";

    @Value("${xxx_ads_url}")
    private String dbUrl;
    @Value("${xxx_ads_username}")
    private String dbUser;
    @Value("${xxx_ads_password}")
    private String dbPassword;

    @Bean(name = "adsDataSource")
    public DataSource adsDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl(dbUrl);
        dataSource.setUsername(dbUser);
        dataSource.setPassword(dbPassword);
        return dataSource;
    }

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

    @Bean(name = "adsSqlSessionFactory")
    public SqlSessionFactory adsSqlSessionFactory(@Qualifier("adsDataSource") DataSource adsDataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(adsDataSource);
        return sessionFactory.getObject();
    }
}

Mapper

Mapper是mybatis的DAL层接口,其实现是由mybatis内部完成的,也就是说,我们只需要定义好接口即可完成CRUD。

com.aliyun.xxx.repository.mybatis.rds包内的Mapper只会用到RDS数据源。

package com.aliyun.xxx.repository.mybatis.rds;

@Mapper
public interface MetaMapper {
    @SelectProvider(type = MetaSelectProvider.class, method = "xxxQueryById")
    @Results(value ={
            @Result(id=true, property="id",column="id",javaType=Long.class,jdbcType=JdbcType.BIGINT),
            ...
            @Result(property="gmtCreate",column="gmt_create",javaType=Date.class,jdbcType=JdbcType.TIMESTAMP)})
    List<XxxPojo> xxxQueryById(@Param("xxxId") String xxxId);
}

上述Mapper定义了一个Select方法,@SelectProvider用于定义具体的SQL语句,@Results用于定义具体的表字段与POJO属性的映射。

MetaSelectProvider可以使用MyBatis的API完成SQL的拼装。

public class MetaSelectProvider {
    private static final String xxxSQL = "id, ...,gmt_create";

    public String xxxQueryById(Map<String, Object> parameter) {
        org.apache.ibatis.jdbc.SQL sql = new org.apache.ibatis.jdbc.SQL();
        sql.SELECT(xxxSQL).FROM("table_name").WHERE("biz_id=#{xxxId}");
        return sql.toString();
    }
}

DAO

@Repository
public class XxxDAO {
    @Autowired
    private MetaMapper metaMapper;

    public List<XxxPojo> xxxQueryById(String xxxId) throws DataAccessException {
        return metaMapper.xxxQueryById(xxxId);
    }
}

SpringBootApplication

Spring Boot的入口类定义如下:

@SpringBootApplication
@PropertySource("file:/opt/xxx/xxx.properties")
public class XxxApplication {
    public static void main(String[] args) {
        SpringApplication.run(XxxApplication.class, args);
    }
}

测试类

使用Spring的上下文,完成单元测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = XxxApplication.class)
public class TestXxxDAO {
    private static final Logger logger = LogManager.getLogger(RelevanceResource.class);
    @Autowired
    private XxxDAO dao;

    @Test
    public void testXxxById() {
        String xxxId = "C00018";
        List<XxxPojo> list = dao.xxxQueryById(xxxId);
        Assert.assertNotNull(list);
        logger.info(...);
    }
}
时间: 2024-09-21 19:25:45

Spring Boot下配置MyBatis多数据源的相关文章

Spring Boot自动配置

在上篇文章如何运行Spring Boot应用中,已经熟悉了如何通过maven或者gradle创建一个Spring Boot应用,这篇文章主要学习Spring Boot的自动配置,包括注解的使用以及一些配置约束等等. 关于Spring Boot的特性介绍,可以参考Spring Boot特性. 主应用类 在Spring Boot应用中,我们通常将主应用类放置于应用的根包中,例如,com.javachen.example.主应用类有main方法,并且使用了@EnableAutoConfiguratio

【ActiveMQ】2.spring Boot下使用ActiveMQ

在spring boot下使用ActiveMQ,需要一下几个条件 1.安装并启动了ActiveMQ,参考:http://www.cnblogs.com/sxdcgaq8080/p/7919489.html 2.搭建了spring boot项目,参考:http://www.cnblogs.com/sxdcgaq8080/p/7712874.html ===========================================================================

多数据源-JSPXCMS系统里面的Spring Data JPA配置2个数据源

问题描述 JSPXCMS系统里面的Spring Data JPA配置2个数据源 JSPXCMS系统里面的Spring Data JPA配置2个数据源

【spring boot】10.spring boot下的单元测试

spring boot下的单元测试,思前想后还是需要单独用一章篇幅来看看. 然后在看了介绍和使用时候,我感觉并不想多去看了. 但是还是给后来人留下参考的路径: 官网说明:https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4[看了这篇说明,下面的问题2即可迎刃而解] 完整例子使用单元测试:https://segmentfault.com/a/1190000011420910[看了这个之后,你就打消了要把它

spring mvc-关于springMVC mybatis 多数据源配置问题

问题描述 关于springMVC mybatis 多数据源配置问题 12:59:38,349 ERROR [STDERR] SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder] 12:59:38,382 WARN [ConfigurationClassEnhancer] @Bean method SpringIocMappingConfig.mapperScannerC

Spring boot将配置属性注入到bean 专题

@ConfigurationProperties和@value都是将外部属性注入到对象 @ConfigurationProperties很方便使用. 比用@value注解好吗? 在特定的方案中是的,这只是一个选择问题 @EnableConfigurationProperties //开启属性注入,有此注解就可以通过@autowired注入, 是配合@ConfigurationProperties使用的.如果没有@EnableConfigurationProperties,则使用@Configur

Spring Boot中使用MyBatis注解配置详解

MyBatis MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 传参方式 下面通过几种不同传参方式来实现前文中实现的插入操作. 使用@Param 在之前的整合示例中我们已经使用了这种最简单的传参方式,如下: @I

Spring Boot自动配置源码

SpringBoot初始化上下文环境 SpringBoot会从META-INF/spring.factories文件中加载Initializers,Auto Configure Initializers用于加载配置(Environment) Auto Configure用于自动配置类 如果是web类型的工程,SpringBoot会创建EmbeddedWebApplicationContext上下文 -> 使用createEmbeddedServletContainer方法创建内嵌的servlet

【spring boot】13.在spring boot下使用多线程

使用场景: 方法处理到某一步,需要将信息交给另一个线程去处理!! =================================================================================== 第一种:最简单的Runnable public void test(String msg){ System.out.println(Thread.currentThread().getName()+":"+msg); Runnable runnable =