spring boot整合mybatis多數據源並加入事務管理

寫這篇文章的初衷是應爲最近一直在學習spring boot相關的一些東西,而在spring boot整合mybatis中相關的博客有很多,可多數都是描述不清然人產生疑惑,或者乾脆就是存在問題。尤其是在事務管理這裏,大家說的都很含糊,於是在經過最近自己的學習後,決定把自己整理的資歷拿出了分享。

##多數據源

關於多數據源的實現,這裏提供兩種思路

  • 通過指定不同包下的dao層實現來解決

  • 通過service層動態指定數據源

下面會對這兩種思路做分別的實現。


##一.多數據源的基本配置

開始前我們先準備兩個庫,這裏使用MySQL數據庫
test庫和test_bac用來模擬兩個數據源
在兩個庫下分別創建一張user表

CREATE TABLE user (
id int(11) NOT NULL,
user_name varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
age int(11) DEFAULT NULL,
sex bit(1) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


  1. 首先創建一個空spring boot工程
  2. 工程結構如下
    工程結構圖

  1. pom.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<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>

	<groupId>com.wxy</groupId>
	<artifactId>double-data-source</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>double-data-source</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.7.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.1</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

2.在application.properties中配置數據庫信息

# test庫
spring.datasource.db1.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8
spring.datasource.db1.username=root
spring.datasource.db1.password=root
spring.datasource.db1.driver-class-name=com.mysql.jdbc.Driver
# 連接池配置
# 省略

# tes_bac庫
spring.datasource.db2.url=jdbc:mysql://127.0.01:3306/test_bac?characterEncoding=UTF-8
spring.datasource.db2.username=root
spring.datasource.db2.password=root
spring.datasource.db2.driver-class-name=com.mysql.jdbc.Driver

其中db1和db2分別區分了兩個數據源


3.在spring boot的啓動類裏面使用@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

目的是將spring boot自帶的DataSourceAutoConfiguration禁掉,因爲它會讀取application.properties文件的spring.datasource.*


4.上一步中,我們禁用了spring boot 的數據源的自動配置,因此我們要手動添加配置,新建一個config包,並建一個DataSourceConfig.java類,來配置我們的數據源。
DataSourceConfig.java如下

package com.wxy.doubledatasource.config;

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 javax.sql.DataSource;

@Configuration
public class DataSourceConfig {
    // 手動定義數據源的名字,後面自動注入的時候就用這個名字,兩個數據源名字不同,自己定義就好
    @Bean(name = "db1")
    // application.properteis中對應屬性的前綴
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    // 因爲使用了多數據源,所以一定要在一個數據源加上這個註解,否則會報錯
    @Primary
    public DataSource dataSource1() {
        return DataSourceBuilder.create().build();
    }

    // 手動定義數據源的名字,後面自動注入的時候就用這個名字,兩個數據源名字不同,自己定義就好,如果還有其他數據源,就寫多少個
    @Bean(name = "db2")
    // application.properteis中對應屬性的前綴
    @ConfigurationProperties(prefix = "spring.datasource.db2")
    public DataSource dataSource2() {
        return DataSourceBuilder.create().build();
    }
}


  1. 接下來我們還需要配置SQLSessionFactory,數據源與sqlsessionfactory是一一對應的,這裏以第一個數據源爲例,因爲後面無論有多少個都是差不多的,只自動注入的數據源會有所差別。
package com.wxy.doubledatasource.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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 javax.sql.DataSource;

@Configuration
// 指定不同數據源所用的dao,調用不同的dao以啓用不同的數據源。
@MapperScan(basePackages = {"com.wxy.doubledatasource.dao.db1"}, sqlSessionFactoryRef = "sqlSessionFactory1")
public class MybatisDB1Config {

    @Autowired
    @Qualifier("db1")// 指定db1數據源,即我們在DataSourceConfig中設置的@bean("db1")對應
    private DataSource db1;

    @Bean
    @Primary// 只有主數據源需要,與DataSourceConfig中的對應
    public SqlSessionFactory sqlSessionFactory1() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(db1); // 使用db1數據源, 連接test庫
        // 可以在這裏指定是否使用mapper映射文件,這裏爲了簡單就沒有配置,如果需要配置的話,要加到resources目錄下面,
        // 否則需要在pom文件中設置對靜態文件的加載
//        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/*.xml"));

        return factoryBean.getObject();

    }
@Bean
    @Primary
    public SqlSessionTemplate sqlSessionTemplate1() throws Exception {
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory1()); // 使用上面配置的Factory
        return template;
    }

}


6.下面我們開始使用剛剛配製好的數據源,首先把剛剛指定的dao層的包建好,然後建對應的接口,以簡單的插入爲例

package com.wxy.doubledatasource.dao.db1;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface UserDao1 {
    @Insert("insert into user values(#{id}, #{userName}, #{age}, #{sex})")
    int insert(@Param("id") int id, @Param("userName") String userName, @Param("age") int age, @Param("sex") boolean sex);
}


7.這樣就可以使用了,還有事務

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章