SpringBoot集成多数据源解析

 更新时间:2017年11月11日 09:01:32   作者:不清不慎  
这篇文章主要介绍了SpringBoot集成多数据源解析,具有一定参考价值,需要的朋友可以了解下。

一,前面我们介绍了springboot的快速启动,大家肯定对springboot也有所了解,下面我们来介绍一下springboot怎么集成多数据源。

在有的项目开发中需要在一个项目中访问多个数据源或者两个项目之间通信(实质上是互相访问对方的数据库),在这里,我们介绍一下在一个项目中如何集成多个数据源(即访问多个不同的数据库),因为在项目中有时会有这种需求,比如在一个大型项目开发中,一个数据库中保存数据的索引,各种使用频繁的数据,另一个数据库中保存其他的数据。

1.下面我们来讨论一个问题,怎么集成多数据源,就是怎么让一个项目访问多个数据库?

有的人会说使用注解,没错,这是一种办法,因为springboot对的最大好处就是避免了繁琐的xml配置文件,大量的使用注解来开发,方便简洁,但是在这里如果集成多数据源使用注解的话会很麻烦,有没有其他的办法呢?答案是肯定的,我们可以分模板来访问多个数据库,也就是分包。

2.如何分包来访问多个数据源?

在这里,我们用一个简单的案例来说明,我们访问新建一个spingboot项目,访问test1,test2这两个数据库,首先,我们先看代码。

首先,我们需要导入相关依赖在pom文件中,这里,因为我的项目已经提前有了父pom,所以不再考虑依赖的版本问题,怎么建立父pom可参考上一篇文章。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <parent>
  <groupId>cn.shinelon.springboot</groupId>
  <artifactId>microboot</artifactId>
  <version>0.0.1-SNAPSHOT</version>
 </parent>
 <artifactId>springboot-MultiDatasources</artifactId>
 <packaging>war</packaging>


 <!-- maven项目packaging改为war类型时,必须要加这个插件 -->
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 测试springboot的依赖 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>

  <!-- 测试时加入这两个依赖,当修改代码的时候就不用每次修改后重启服务器了 -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>springloaded</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
  </dependency>
  <!-- springboot 集成jsp必须要借助这两个依赖 -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
  </dependency>
  <!-- springboot集成mybatis -->
  <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.0</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>
 </dependencies>
</project>

在上面配置的pom文件中,有点要说明,因为要访问数据库,所以我整合了mybatis,还有一个是整合jsp,不过在这个项目中无关,是我之前写代码留下来的,可不必关心。

下面,我们还要在scr/main/sources目录下新建一个application.properties资源文件,注意,这个文件名必须是application,这个是固定的,springboot默认访问该文件,不要自己乱改名称。然后在这个资源文件中配置自定义数据源。

spring.datasource.test1.driverClassName=com.mysql.jdbc.Driver
spring.datasource.test1.url=jdbc:mysql://localhost:3306/test1
spring.datasource.test1.username=root
spring.datasource.test1.password=.....

spring.datasource.test2.driverClassName=com.mysql.jdbc.Driver
spring.datasource.test2.url=jdbc:mysql://localhost:3306/test2
spring.datasource.test2.username=root
spring.datasource.test2.password=.....

配置好数据源后我们就可以开进行分模块来访问这两个数据源了。首先在src/mian/java目录下创建好各个包,然后开始开发,新建一个datasource包来放置需要访问的两个数据源的代码,然后在新建两个模块包test1和test2,从包名我们就可以看出来这两个包是用来操作这两个数据库,在这两个包下可以分别建立DAO层和service层的包,然后建立一个controller控制层。下面是项目的目录树图。

然后我们来写DataSource中的代码,其实就是像我们以前在xml文件中配置的SqlSessionFactory和数据源一个原理。

import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@Configuration
@MapperScan(basePackages="cn.shinelon.test1",sqlSessionFactoryRef="test1SqlSessionFactory")
public class Datasource1 {
  /**
   * 配置test1数据库
   * @return
   */
  @Bean(name="test1Datasource")
  @ConfigurationProperties(prefix="spring.datasource.test1")
  public DataSource testDatasource() {
    return DataSourceBuilder.create().build();
  }
  /**
   * 创建SqlSessionFactory
   * @param dataSource
   * @return
   * @throws Exception
   */
  @Bean(name="test1SqlSessionFactory")
  public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1Datasource")DataSource dataSource) 
      throws Exception {
    SqlSessionFactoryBean bean=new SqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    //如果还有分页等其他事务
//   bean.setMapperLocations(new PathMatchingResourcePatternResolver().
//       getResources("classpath:mybatis/test1/*.xml"));
    return bean.getObject();
  }
  /**
   * 配置事务管理
   * @param dataSource
   * @return
   */
  @Bean(name="test1TransactionManager")
  public DataSourceTransactionManager testTransactionManager(
      @Qualifier("test1Datasource")DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
  }
  @Bean(name="test1SqlSessionTemplate")
  public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory")
  SqlSessionFactory sqlSessionFactory) {
    return new SqlSessionTemplate(sqlSessionFactory);
  }
}

上面的是访问的test1数据库的配置,需要注意的是@ConfigurationProperties(prefix=”spring.datasource.test1”)这个配置中的属性prefix的值必须和资源文件中的前缀是一样的,否则是访问不到的,还有@Primary ,如果不加这个注解,启动将会报错,因为服务器先要有一个默认不知道默认要先访问的数据源是哪个,必须指明,下面是test2数据库的配置,和上面一样的。

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

@Configuration
@MapperScan(basePackages="cn.shinelon.test2",sqlSessionFactoryRef="test2SqlSessionFactory")
@Primary    //指定 默认的访问的数据源
public class Datasource2 {
  /**
   * 配置test2数据库
   * @return
   */
  @Bean(name="test2Datasource")
  @ConfigurationProperties(prefix="spring.datasource.test2")
  @Primary    //指定 默认的访问的数据源
  public DataSource testDatasource() {
    return DataSourceBuilder.create().build();
  }
  /**
   * 创建SqlSessionFactory
   * @param dataSource
   * @return
   * @throws Exception
   */
  @Bean(name="test2SqlSessionFactory")
  @Primary    //指定 默认的访问的数据源
  public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2Datasource")DataSource dataSource) 
      throws Exception {
    SqlSessionFactoryBean bean=new SqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    //如果还有分页等其他事务
//   bean.setMapperLocations(new PathMatchingResourcePatternResolver().
//       getResources("classpath:mybatis/test2/*.xml"));
    return bean.getObject();
  }
  /**
   * 配置事务管理
   * @param dataSource
   * @return
   */
  @Bean(name="test2TransactionManager")
  @Primary    //指定 默认的访问的数据源
  public DataSourceTransactionManager testTransactionManager(
      @Qualifier("test2Datasource")DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
  }

  @Bean(name="test2SqlSessionTemplate")
  public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test2SqlSessionFactory")
  SqlSessionFactory sqlSessionFactory) {
    return new SqlSessionTemplate(sqlSessionFactory);
  }
}

然后我们在每一个模块中写DAO层和service代码来进行操作。
DAO层代码如下

public interface User1Dao {
  @Insert("insert into user values(null,#{username},#{age})")
  public void insert(@Param("username")String username,@Param("age")int age);
}

在这里,我们向数据库插入一条数据。
service层代码如下

@Service
public class User1Service {
  @Autowired
  public User1Dao user1Dao;

  public void insert(String username,int age) {
    user1Dao.insert(username, age);
  }
}

test2包下DAO层和service层的代码都是同样的,这里就省略了。
然后我们来开始写controller层的代码。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.shinelon.test1.services.User1Service;
import cn.shinelon.test2.services.User2Service;

@SpringBootApplication
@ComponentScan(basePackages={"cn.shinelon.datasource","cn.shinelon.test1","cn.shinelon.test2"})
@RestController
public class UserController {
  @Autowired
  public User1Service user1Service;
  @Autowired
  public User2Service user2Service;
  @RequestMapping("/add")
  public String insert(String username,int age) {
    user1Service.insert(username, age);
    user2Service.insert(username, age);
    return "insert success";
  }

  public static void main(String[] args) {
    SpringApplication.run(UserController.class, args);
  }
}

上面代码中 ,需要注意的是@ComponentScan(basePackages={“cn.shinelon.datasource”,”cn.shinelon.test1”,”cn.shinelon.test2”})这个注解,必须添加,这样服务器才会扫描到这几个包中的配置。

下面我们补全代码,还要建立一个实体类

public class User {
  private int id;
  private String username;
  private int age;
  //省略get,set方法
  }

最后的整个项目图如下

总结

以上就是本文关于SpringBoot集成多数据源解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:Maven管理SpringBoot Profile详解springboot扫描自定义的servlet和filter代码详解浅谈Springboot之于Spring的优势等,有什么问题可以随时留言,小编会及时回复大家的。感谢朋友们对本站的支持!

相关文章

  • 使用java实现telnet-client工具分享

    使用java实现telnet-client工具分享

    这篇文章主要介绍了使用java实现telnet-client工具,需要的朋友可以参考下
    2014-03-03
  • Spring中Transactional注解使用的心得(推荐)

    Spring中Transactional注解使用的心得(推荐)

    这篇文章主要介绍了Spring中Transactional注解使用的心得,事务是用来控制数据的ACID特性的,用于保证数据的正确性和完整性,需要的朋友可以参考下
    2022-10-10
  • 关于Java中XML Namespace 命名空间问题

    关于Java中XML Namespace 命名空间问题

    这篇文章主要介绍了Java中XML Namespace 命名空间,XML命名空间是由国际化资源标识符 (IRI) 标识的 XML 元素和属性集合,该集合通常称作 XML“词汇”,对XML Namespace 命名空间相关知识感兴趣的朋友一起看看吧
    2021-08-08
  • 实例详解Java实现图片与base64字符串之间的转换

    实例详解Java实现图片与base64字符串之间的转换

    这篇文章主要介绍了Java实现图片与base64字符串之间的转换实例代码,非常不错,具有参考借鉴价值,需要的朋友参考下
    2016-12-12
  • Google Guava 缓存工具使用详解

    Google Guava 缓存工具使用详解

    这篇文章主要介绍了Guava自加载缓存LoadingCache使用指南,通过这些内容介绍,了解了LoadingCache的基本原理和用法,包括如何创建和配置缓存,以及如何结合Java 8的特性来优化代码,需要的朋友可以参考下
    2023-12-12
  • Java学习随记之多线程编程

    Java学习随记之多线程编程

    这篇文章主要介绍了Java中的多线程编程的相关知识,文中的示例代码介绍详细,对我们的学习或工作有一定的价值,感兴趣的小伙伴可以了解一下
    2021-12-12
  • Spring boot打包jar分离lib和resources方法实例

    Spring boot打包jar分离lib和resources方法实例

    这篇文章主要介绍了Spring boot打包jar分离lib和resources方法实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • Java深入讲解instanceof关键字的使用

    Java深入讲解instanceof关键字的使用

    instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符。instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型
    2022-05-05
  • Spring AOP实现声明式事务机制源码解析

    Spring AOP实现声明式事务机制源码解析

    这篇文章主要为大家介绍了Spring AOP实现声明式事务机制源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • java数据结构基础:栈

    java数据结构基础:栈

    这篇文章主要介绍了Java的数据解构基础,希望对广大的程序爱好者有所帮助,同时祝大家有一个好成绩,需要的朋友可以参考下,希望能给你带来帮助
    2021-07-07

最新评论