Mybatis操作多数据源的实现

Mybatis是一种优秀的ORM框架,对于开发人员来说,在数据库连接方面有许多选择,包括多数据源。在这里,我们将详细解释如何在Mybatis中实现多数据源。主要分为以下三个部分:

1.配置多数据源的文件

Mybatis可以配置多个数据源,需要在mybatis-config.xml中添加以下内容:

<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC"/>
    <dataSource type="POOLED">
      <property name="driver" value="${jdbc.driver}"/>
      <property name="url" value="${jdbc.url}"/>
      <property name="username" value="${jdbc.username}"/>
      <property name="password" value="${jdbc.password}"/>
    </dataSource>
  </environment>
  <environment id="development2">
    ...
  </environment>
</environments>

其中,default属性指定默认的环境,可以在SqlSessionFactoryBuilderbuild()方法中指定使用哪个环境。environment元素定义了一个特定的环境,包含了数据库的链接信息。在每个environment中,可以定义一个或多个dataSource元素,分别指向不同的数据源。例如,在这里我们添加了两个数据源。

注意:在以上代码中,你需要把${jdbc.driver}${jdbc.url}等属性值替换成具体的值。

2.创建SqlSessionFactory对象

当多个environment中的dataSource元素指向不同的数据源,我们需要在运行时选择使用哪个数据源。为此,我们可以使用SqlSessionFactory的构造函数:

String environment = ...; // 选择要使用的环境id
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, environment);

上面的代码通过SqlSessionFactoryBuilderbuild()方法选择特定的数据源,返回一个SqlSessionFactory,后面我们就可以使用这个工厂来创建SqlSession,然后操作数据库。

3.注解@MapperScan

多数据源配置完后,需要在应用程序的入口处,注解@MapperScan才能扫描到多个Mapper,如下:

@SpringBootApplication
@MapperScan({"com.example.mapper1", "com.example.mapper2"})
public class Application {

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

}

以上是多数据源实现的主要三个步骤。下面,我们来看两个具体的示例。

示例一

假设我们有两个数据库,一个是test1,另一个是test2。并且后面的操作是在Spring Boot上实现的。为了简化操作,在这里我们将使用默认的数据源test1来创建表和填充数据。然后,我们将使用test2,显式地将一个映射文件指向它,并且从它中查询一些数据。

首先,我们将使用默认的数据源创建表和填充数据,可以使用以下SQL语句:

-- 创建表
CREATE TABLE user (
  id BIGINT(20) PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(32) DEFAULT NULL,
  age INT(11) DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;

-- 插入数据
INSERT INTO user (name, age) VALUES ('Tom', 20);
INSERT INTO user (name, age) VALUES ('Jerry', 18);
INSERT INTO user (name, age) VALUES ('Lucy', 25);

然后,我们需要在application.properties中指定两个数据源的相关信息:

# test1
spring.datasource.url=jdbc:mysql://localhost:3306/test1?useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Hongkong
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# test2
test2.datasource.url=jdbc:mysql://localhost:3306/test2?useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Hongkong
test2.datasource.username=root
test2.datasource.password=123456
test2.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

需要注意在test2数据源前加上test2.前缀。

接下来我们在test2数据源中,添加一个Mapper接口UserMapper,并在其中添加如下方法:

package com.example.mapper2;

import com.example.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserMapper {

    @Select("SELECT * FROM user")
    List<User> queryAll();

}

接下来,在启动类中加入如下代码:

@Configuration
@MapperScan("com.example.mapper1")
public class MybatisConfig {

    @Qualifier("test1")
    @Bean(name = "test1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource test1DataSource() {
        return DataSourceBuilder.create().build();
    }

    @Qualifier("test2")
    @Bean(name = "test2DataSource")
    @ConfigurationProperties(prefix = "test2.datasource")
    public DataSource test2DataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "routingDataSource")
    public AbstractRoutingDataSource routingDataSource(@Qualifier("test1DataSource") DataSource test1DataSource,
                                                       @Qualifier("test2DataSource") DataSource test2DataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DatabaseType.TEST1, test1DataSource);
        targetDataSources.put(DatabaseType.TEST2, test2DataSource);

        AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
            @Override
            protected Object determineCurrentLookupKey() {
                return DatabaseContextHolder.getDatabaseType();
            }
        };

        routingDataSource.setDefaultTargetDataSource(test1DataSource);
        routingDataSource.setTargetDataSources(targetDataSources);

        DatabaseContextHolder.setDatabaseType(DatabaseType.TEST1);

        return routingDataSource;
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("routingDataSource") AbstractRoutingDataSource routingDataSource) throws IOException {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(routingDataSource);
        sessionFactory.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath:com/example/mapper/**/*.xml"));
        return sessionFactory;
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

上面的配置,我们定义了两个数据源的Bean对象,通过AbstractRoutingDataSource对象实现路由功能,将不同的SQL语句发往不同的数据源。在此,我们使用了一个自定义的枚举类DatabaseType,如下:

public enum DatabaseType {
    TEST1, TEST2
}

还需要一个自定义的DatabaseContextHolder对象来保存当前数据源,如下:

public class DatabaseContextHolder {

    private static final ThreadLocal<DatabaseType> CONTEXT_HOLDER = new ThreadLocal<>();

    public static void setDatabaseType(DatabaseType type) {
        CONTEXT_HOLDER.set(type);
    }

    public static DatabaseType getDatabaseType() {
        return CONTEXT_HOLDER.get();
    }

    public static void clearDatabaseType() {
        CONTEXT_HOLDER.remove();
    }

}

以上是此示例的全部内容。在此之后,我们就可以使用UserMapper查询test2数据源的user表:

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public List<User> queryAll() {
        DatabaseContextHolder.setDatabaseType(DatabaseType.TEST2);
        List<User> users = userMapper.queryAll();
        DatabaseContextHolder.clearDatabaseType();
        return users;
    }

}

注意,在这里我们使用了DatabaseContextHolder类来切换数据源。

示例二

下面,我们再看一个简化版的多数据源实现:假设我们有两个数据源:一个是test1数据源,包含一个名为user的表;另一个是test2数据源,包含一个名为customer的表。我们需要在这两个数据源中分别查询这两个表的数据。

与示例一不同的是,我们这里不需要在运行时切换数据源,因为我们知道要使用哪个数据源。因为我们不使用AbstractRoutingDataSource路由,而是手动创建两个SqlSessionFactoryBean对象,并为每个对象设置不同的DataSource

首先,需要在application.properties中为这两个数据源声明相关的属性:

spring.datasource.test1.url=jdbc:mysql://localhost:3306/test1?useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Hongkong
spring.datasource.test1.username=root
spring.datasource.test1.password=123456
spring.datasource.test1.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.test2.url=jdbc:mysql://localhost:3306/test2?useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Hongkong
spring.datasource.test2.username=root
spring.datasource.test2.password=123456
spring.datasource.test2.driver-class-name=com.mysql.cj.jdbc.Driver

创建两个SqlSessionFactoryBean后,就可以设置它们的DataSource属性。首先,我们来看test1数据源:

@Configuration
public class DataSource1Config {

    @Value("${spring.datasource.test1.url}")
    private String url;

    @Value("${spring.datasource.test1.username}")
    private String username;

    @Value("${spring.datasource.test1.password}")
    private String password;

    @Value("${spring.datasource.test1.driver-class-name}")
    private String driverClassName;

    @Bean(name = "test1DataSource")
    public DataSource test1DataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean(name = "test1SqlSessionFactory")
    public SqlSessionFactoryBean test1SqlSessionFactory(@Qualifier("test1DataSource") DataSource test1DataSource) throws IOException {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(test1DataSource);
        sessionFactory.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath:com/example/mapper/test1/*.xml"));
        return sessionFactory;
    }

    @Bean(name = "test1SqlSessionTemplate")
    public SqlSessionTemplate test1SqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

上面代码中,我们需要通过属性文件获取各种连接参数的值,然后创建DriverManagerDataSource对象。

接下来,我们看一下test2数据源的配置:

@Configuration
public class DataSource2Config {

    @Value("${spring.datasource.test2.url}")
    private String url;

    @Value("${spring.datasource.test2.username}")
    private String username;

    @Value("${spring.datasource.test2.password}")
    private String password;

    @Value("${spring.datasource.test2.driver-class-name}")
    private String driverClassName;

    @Bean(name = "test2DataSource")
    public DataSource test2DataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean(name = "test2SqlSessionFactory")
    public SqlSessionFactoryBean test2SqlSessionFactory(@Qualifier("test2DataSource") DataSource test2DataSource) throws IOException {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(test2DataSource);
        sessionFactory.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath:com/example/mapper/test2/*.xml"));
        return sessionFactory;
    }

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

}

以上是这个简化版示例的全部内容。在这里,我们使用两个不同的SqlSessionFactoryBean对象,为每个对象设置不同的数据源和Mapper文件位置即可。

至此,我们已经讲解了Mybatis操作多数据源的实现攻略。希望可以帮助你更好地理解和应用多数据源。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Mybatis操作多数据源的实现 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • C#实现将文件转换为XML的方法

    以下是标准的Markdown格式文本,包含标题、代码块和示例的详细讲解“C#实现将文件转换为XML的方法”的完整攻略。 C#实现将文件转换为XML的方法 准备工作 在使用C#将文件转换为XML之前,需要准备以下的工作: 了解如何访问文件系统。C#可以使用System.IO命名空间来访问文件系统,具体请参考MSDN文档。 熟悉如何使用XML。C#内置了XML相…

    Java 2023年5月20日
    00
  • Java的Struts框架报错“NullActionFormException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“NullActionFormException”错误。这个错误通常由以下原因之一起: 表单对象为空:如果表单对象为空,则可能会出现此。在这种情况下,需要检查表单对象以解决此问题。 配置错误:如果配置文件中没有正确配置,则可能会出现此。在这种情况下,需要检查文件以解决此问题。 以下是两个实例: 例 1 如果表单对…

    Java 2023年5月5日
    00
  • 阿里外包电话面试经历记录

    阿里外包电话面试经历记录攻略 准备材料 在参加阿里外包电话面试之前,需要准备以下材料: 个人简历 阿里云账号 电脑或智能手机等通讯设备 注意事项 提前熟悉阿里巴巴的公司文化、产品、服务等; 如需使用翻译软件,应提前测试并保证其稳定性; 避免私下安排面试时间,应遵循官方约定的面试时间。 面试流程 第一部分:自我介绍 在面试开始时,面试官会让你进行自我介绍。应该…

    Java 2023年6月15日
    00
  • Maven引用自定义jar包方式

    以下是使用 Maven 引用自定义 JAR 包的完整攻略: 1. 使用项目本地依赖库 如果你的 JAR 包已经是 Maven 项目,可以使用 Maven 提供的本地依赖库功能。在项目中,将 JAR 包命名为 <artifactId>-<version>.jar,并放在项目的 /lib 目录下,这样 Maven 就会将其加入本地依赖库中…

    Java 2023年5月19日
    00
  • 用intellij Idea加载eclipse的maven项目全流程(图文)

    以下是详细讲解“用IntelliJ Idea加载Eclipse的Maven项目全流程”的完整攻略。 步骤1:安装IntelliJ Idea 首先,需要在本地安装IntelliJ Idea,如果还没有安装,请官网下载并安装。 步骤2:打开IntelliJ Idea 安装完成后,打开IntelliJ Idea,点击菜单中的“Import Project” 步骤3…

    Java 2023年5月20日
    00
  • 详解在SpringBoot中@Transactional事物操作和事物无效问题排查

    详解在SpringBoot中@Transactional事物操作和事物无效问题排查 事物被认为是许多企业应用程序的重要组成部分。在SpringBoot中,我们可以使用@Transactional注解来处理事务。但有时候,这个注解可能无法正常工作,导致事物无效。这时我们需要排查问题。下面是详细攻略: 问题排查 无效的事物操作可能是由以下原因引起的: 事物管理器…

    Java 2023年5月20日
    00
  • 深入介绍Spring框架及故障排除

    深入介绍Spring框架及故障排除 Spring框架是一个开源的Java平台应用程序框架,它可以帮助开发人员快速开发企业级Java应用程序。该框架提供了许多功能来简化开发过程,例如IoC容器,数据访问支持,Web应用程序开发,AOP和安全性等。但是,在使用Spring框架时,您可能会遇到一些问题。这篇文章将提供一些故障排除技巧,以帮助您解决Spring框架的…

    Java 2023年5月19日
    00
  • Spring Cloud Gateway编码实现任意地址跳转的示例

    首先我们来介绍一下Spring Cloud Gateway。 Spring Cloud Gateway是Spring Cloud生态中的一个全新项目,它是基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,旨在为微服务提供一种简单而统一的方式来访问外部服务。 那么,如何实现Spring Cloud Gat…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部