springboot mybatis plus 多数据源 mysql sqllite

简介

在现代的Web应用程序中,使用多个数据库是非常常见的。有时候我们需要将数据存储在不同的数据库中,例如将敏感数据存储在私有数据库中,将公共数据存储在共享数据库中。在本文中,我们将探讨如何在Spring Boot中使用MyBatis Plus实现多数据源,并使用MySQL和SQLite作为示例数据库。

准备工作

在开始编写代码之前,我们需要做一些准备工作:

  1. 安装Java JDK和IDE(例如Eclipse或IntelliJ IDEA)
  2. 创建一个Spring Boot项目
  3. 添加以下依赖项到pom.xml文件中:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>

<dependency>
    <groupId>org.xerial</groupId>
    <artifactId>sqlite-jdbc</artifactId>
    <version>3.36.0.3</version>
</dependency>

配置多数据源

在Spring Boot中配置多个数据源非常简单。我们只需要在application.propertiesapplication.yml文件中定义多个数据源的连接信息。

首先,我们需要配置MySQL数据源。在application.properties文件中添加以下配置:

spring.datasource.mysql.url=jdbc:mysql://localhost:3306/mysql_database
spring.datasource.mysql.username=root
spring.datasource.mysql.password=123456
spring.datasource.mysql.driver-class-name=com.mysql.cj.jdbc.Driver

接下来,我们需要配置SQLite数据源。在application.properties文件中添加以下配置:

spring.datasource.sqlite.url=jdbc:sqlite:/path/to/sqlite_database.db
spring.datasource.sqlite.driver-class-name=org.sqlite.JDBC

创建实体类和Mapper

我们将创建两个实体类UserProduct,分别表示用户和产品:

// User.java
public class User {
    private Long id;
    private String name;
    private String email;
    
    // getters and setters
}

// Product.java
public class Product {
    private Long id;
    private String name;
    private BigDecimal price;
    
    // getters and setters
}

接下来,我们需要创建两个Mapper接口UserMapperProductMapper,用于与数据库交互:

// UserMapper.java
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

// ProductMapper.java
@Mapper
public interface ProductMapper extends BaseMapper<Product> {
}

配置MyBatis Plus

在Spring Boot中使用MyBatis Plus非常简单。我们只需要配置SqlSessionFactoryTransactionManager即可。

首先,将以下代码添加到application.java文件中:

// MybatisPlusConfig.java
@Configuration
@MapperScan("com.example.mapper")
public class MybatisPlusConfig {
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("mysqlDataSource") DataSource mysqlDataSource,
            @Qualifier("sqliteDataSource") DataSource sqliteDataSource) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(routingDataSource(mysqlDataSource, sqliteDataSource));
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:/mapper/*.xml"));
        return sqlSessionFactory.getObject();
    }

    @Bean
    public DataSourceTransactionManager transactionManager(@Qualifier("mysqlDataSource") DataSource mysqlDataSource,
            @Qualifier("sqliteDataSource") DataSource sqliteDataSource) {
        DataSourceTransactionManager transactionManager = new DynamicDataSourceTransactionManager();
        transactionManager.setDataSource(routingDataSource(mysqlDataSource, sqliteDataSource));
        return transactionManager;
    }

    private DataSource routingDataSource(DataSource mysqlDataSource, DataSource sqliteDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DatabaseType.MYSQL, mysqlDataSource);
        targetDataSources.put(DatabaseType.SQLITE, sqliteDataSource);

        DynamicRoutingDataSource routingDataSource = new DynamicRoutingDataSource();
        routingDataSource.setDefaultTargetDataSource(mysqlDataSource);
        routingDataSource.setTargetDataSources(targetDataSources);

        return routingDataSource;
    }
}

接下来,我们需要创建一个DynamicDataSourceTransactionManager类,用于多数据源的事务管理:

public class DynamicDataSourceTransactionManager extends DataSourceTransactionManager {
    @Override
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        boolean readOnly = definition.isReadOnly