springboot+mybatis多数据源实现

        之前项目需要使用多数据库的功能,所以研究了下多数据库的配置,并且一并研究了多数据源的实现,但是因为多数据源网上资料较多,所以本不打算发文出来的。直到有位朋友需要使用多数据源功能,但是说实在的,网上能直接拿来照着代码拷贝下来直接用的文章还真不多,大多模棱两可或者干脆就是不知从哪抄了一半,看起来比较痛苦,所以在这里我就发一版自己亲测可用的完整版实现,方便初学者观看,也方便以后自己需要用的时候查阅。

        说明:本文的部分代码来源于网络,但是因为查看了大量文章,所以已经不记得具体是引用了哪个文章了,若原作者发现本文,可与我联系。

        首先注意的是,除了springboot和mybatis的基础引用,使用本文的方法来实现多数据源,需要引用druid线程池,在maven里加入以下引用即可。

<!-- druid线程池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.12</version>
</dependency>

        之后,在application.properties文件中增加数据源配置,如下:

d7.datasource.url=jdbc:dm://localhost:5236
d7.datasource.username=XUJN
d7.datasource.password=shihunshu
d7.datasource.driver-class-name=dm.jdbc.driver.DmDriver

mysql.datasource.url=jdbc:mysql://localhost:3306/demo
mysql.datasource.username=root
mysql.datasource.password=root
mysql.datasource.driver-class-name=com.mysql.jdbc.Driver

        改配置中,我们可以通过命名很明确的区分开我们不同配置对应的数据库,以便于维护。

        之后,我们需要一些辅助类来帮助实现多数据源功能,如下:

/**
 * 作用:
 * 1、保存一个线程安全的DatabaseType容器
 */
public class DatabaseContextHolder {
    private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>();
    
    public static void setDatabaseType(DatabaseType type){
        contextHolder.set(type);
    }
    
    public static DatabaseType getDatabaseType(){
        return contextHolder.get();
    }
}
/**
 * 列出所有的数据源key(常用数据库名称来命名)
 * 注意:
 * 1)这里数据源与数据库是一对一的
 * 2)DatabaseType中的变量名称就是数据库的名称
 */
public enum DatabaseType {
    d7,mysql
}
/**
 * 动态数据源(需要继承AbstractRoutingDataSource)
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    protected Object determineCurrentLookupKey() {
        return DatabaseContextHolder.getDatabaseType();
    }
}

        之后,就是最关键的config类了,类中的一些关键配置会在注释中说明,直接看源码吧:

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

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.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSourceFactory;

/**
 * 多数据源配置类
 */
@Configuration
@MapperScan(basePackages = "com.freddy")
public class MyBatisConfig {

    @Autowired
    private Environment env;

    /**
     * 达梦数据库数据源创建方法
     * @return 创建好的数据源
     * @throws Exception
     */
    @Bean
    public DataSource d7DataSource() throws Exception {
    	//注意,下方env.getProperty的参数,就是你在application.properties中配置的key
        Properties props = new Properties();
        props.put("driverClassName", env.getProperty("d7.datasource.driver-class-name"));
        props.put("url", env.getProperty("d7.datasource.url"));
        props.put("username", env.getProperty("d7.datasource.username"));
        props.put("password", env.getProperty("d7.datasource.password"));
        return DruidDataSourceFactory.createDataSource(props);
    }

    /**
     * mysql数据库数据源创建方法
     * @return 创建好的数据源
     * @throws Exception
     */
    @Bean
    public DataSource mysqlDataSource() throws Exception {
    	//注意,下方env.getProperty的参数,就是你在application.properties中配置的key
        Properties props = new Properties();
        props.put("driverClassName", env.getProperty("mysql.datasource.driver-class-name"));
        props.put("url", env.getProperty("mysql.datasource.url"));
        props.put("username", env.getProperty("mysql.datasource.username"));
        props.put("password", env.getProperty("mysql.datasource.password"));
        return DruidDataSourceFactory.createDataSource(props);
    }

    /**
     * 多数据源配置
     * 特别说明:@Qualifier这个注解是用来指定注入类的,当通过@bean创建实体时,实体的name会默认使用方法名
     * 所以@Qualifier的参数就是上面两个创建数据源的方法的方法名
     * @param d7 达梦数据库数据源
     * @param mysql mysql数据库数据源
     * @return 动态数据源
     */
    @Bean
    @Primary
    public DynamicDataSource dataSource(@Qualifier("d7DataSource") DataSource d7,
            @Qualifier("mysqlDataSource") DataSource mysql) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DatabaseType.d7, d7);
        targetDataSources.put(DatabaseType.mysql, mysql);

        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法
        dataSource.setDefaultTargetDataSource(d7);// 默认的datasource设置为myTestDbDataSource

        return dataSource;
    }

    /**
     * 根据数据源创建SqlSessionFactory
     * @param d7 达梦数据库数据源
     * @param mysql mysql数据库数据源
     * @return SqlSessionFactory
     * @throws Exception
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("d7DataSource") DataSource d7,
            @Qualifier("mysqlDataSource") DataSource mysql) throws Exception{
		SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
		fb.setDataSource(this.dataSource(d7, mysql));
		fb.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage"));
		return fb.getObject();
	}

    /**
     * 配置事务管理器
     * @param dataSource 动态数据源
     * @return DataSourceTransactionManager
     * @throws Exception
     */
    @Bean
    public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) throws Exception {
        return new DataSourceTransactionManager(dataSource);
    }

}

        至此为止,多数据源的基本配置就做好了,那么接下来怎么使用呢?首先我们准备了一个mapper,如下:

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

/**
 * 用户mapper
 * @author freddy
 */
@Mapper
@Repository("userMapper")
public interface UserMapper{
	
	List<UserEntity> findUsers();
	
	List<UserEntity> findUsersMysql();
}

       该mapper里有两个抽象方法,第一个是用于达梦数据库查询用户的,一个是用于mysql数据库查询用户的。当然,这只是测试用的写法,实际项目应用中,应该是不同的数据源有单独的mapper。

        之后在mapper.xml中这样写:

<?xml version="1.0" encoding="UTF-8" ?>      
<!DOCTYPE mapper    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.freddy.mfd7.test.UserMapper">

    <select id="findUsers" resultType="com.freddy.mfd7.test.UserEntity">
		select * from "demo";
    </select>

    <select id="findUsersMysql" resultType="com.freddy.mfd7.test.UserEntity">
		select * from demo;
    </select>
</mapper>

        不同的数据库查询语句可能是不一样的,所以我们写好对应的sql,注入到对应的mapper中即可。

        之后就是调用mapper了,为了方便我这里没分层,就直接在controller中调用mapper了。代码如下,需要注意的地方见注释:

import javax.annotation.Resource;

import org.apache.ibatis.datasource.DataSourceFactory;
import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.freddy.mfd7.test.moreDatasource.DatabaseContextHolder;
import com.freddy.mfd7.test.moreDatasource.DatabaseType;

@ResponseBody
@Controller
public class DemoAction {
	
	DataSourceFactory fac = new PooledDataSourceFactory();
	
	@Resource(name="userMapper")
	private UserMapper userMapper;
	
	@RequestMapping("queryD7")
	public String queryD7(){
		/* 特别注意,在调用mapper之前,必须调用该方法来切换数据源,所以之前直接使用mapper作为dao层的项目,
		可能要新增一个dao层,然后再在dao层中调用mapper了。当然,也可以通过其他方式实现,但是必须有切换数据源的操作。 */
		DatabaseContextHolder.setDatabaseType(DatabaseType.d7);
		return userMapper.findUsers().toString();
	}
	
	@RequestMapping("queryMysql")
	public String queryMysql(){
		DatabaseContextHolder.setDatabaseType(DatabaseType.mysql);
		return userMapper.findUsersMysql().toString();
	}
}

        本文的全部代码就是这样,大家看后有什么不懂的,可以在评论或者私信里问我。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在Spring Boot应用中使用Mybatis和Hikari实现多数据源,可以按照以下步骤进行操作: 1. 在pom.xml文件中添加相关依赖,包括spring-boot-starter-jdbc、mybatis-spring-boot-starter、hikariCP等。 2. 在application.yml配置文件中配置多个数据源,例如: ``` spring: datasource: master: jdbc-url: jdbc:mysql://localhost:3306/master username: root password: root driver-class-name: com.mysql.jdbc.Driver slave: jdbc-url: jdbc:mysql://localhost:3306/slave username: root password: root driver-class-name: com.mysql.jdbc.Driver ``` 3. 创建多个数据源的配置类,例如: ``` @Configuration @MapperScan(basePackages = "com.example.demo.master.mapper", sqlSessionTemplateRef = "masterSqlSessionTemplate") public class MasterDataSourceConfig { @Primary @Bean(name = "masterDataSource") @ConfigurationProperties(prefix = "spring.datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().type(HikariDataSource.class).build(); } @Primary @Bean(name = "masterSqlSessionFactory") public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); return bean.getObject(); } @Primary @Bean(name = "masterTransactionManager") public DataSourceTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Primary @Bean(name = "masterSqlSessionTemplate") public SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } } ``` ``` @Configuration @MapperScan(basePackages = "com.example.demo.slave.mapper", sqlSessionTemplateRef = "slaveSqlSessionTemplate") public class SlaveDataSourceConfig { @Bean(name = "slaveDataSource") @ConfigurationProperties(prefix = "spring.datasource.slave") public DataSource slaveDataSource() { return DataSourceBuilder.create().type(HikariDataSource.class).build(); } @Bean(name = "slaveSqlSessionFactory") public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); return bean.getObject(); } @Bean(name = "slaveTransactionManager") public DataSourceTransactionManager slaveTransactionManager(@Qualifier("slaveDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "slaveSqlSessionTemplate") public SqlSessionTemplate slaveSqlSessionTemplate(@Qualifier("slaveSqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } } ``` 4. 在需要使用数据源的地方使用@Qualifier注解指定数据源,例如: ``` @Service public class UserService { @Autowired @Qualifier("masterSqlSessionTemplate") private SqlSessionTemplate masterSqlSessionTemplate; @Autowired @Qualifier("slaveSqlSessionTemplate") private SqlSessionTemplate slaveSqlSessionTemplate; public List<User> getUsersFromMaster() { return masterSqlSessionTemplate.selectList("com.example.demo.master.mapper.UserMapper.selectAll"); } public List<User> getUsersFromSlave() { return slaveSqlSessionTemplate.selectList("com.example.demo.slave.mapper.UserMapper.selectAll"); } } ``` 这样就可以在Spring Boot应用中使用Mybatis和Hikari实现多数据源了。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值