自学内容网 自学内容网

springboot集成h2数据库并使用多数据源

前言

为了满足客户的需求,我们计划将项目中使用的MySQL数据库迁移至H2数据库。虽然项目已经集成了多数据源,理论上可以正常运作,但在实际操作过程中,我们发现项目启动时无法自动创建表。我们将对此问题进行深入分析,并寻找合适的解决方案以确保项目的顺利运行。

实战

调整依赖

新增h2数据库依赖

<!-- dynamic-datasource 多数据源-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${dynamic-ds.version}</version>
</dependency>
<!-- mybatisPlus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- h2数据库 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>

配置文件

在我们的项目配置中,由于选择了本地连接方式,因此数据库的URL被特意设置为指向本地路径。这样的安排旨在确保数据访问的便捷性和效率,同时也便于管理和维护数据库资源。

--- # 数据源配置
spring:
  h2:
    # 嵌入式(本地)连接
    file_path: D:/H2/db/ # 数据库路径
    db_name: park # 数据库名称
    console:
      path: /h2 # 通过YOUR_URL:PORT/h2访问h2 web consloe
      enabled: true # 程序开启时就会启动h2 web consloe
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    # 动态数据源文档
    dynamic:
      # 性能分析插件(有性能损耗 不建议生产环境使用)
      p6spy: true
      # 设置默认的数据源或者数据源组,默认值即为 master
      primary: master
      # 严格模式 匹配不到数据源则报错
      strict: true
      datasource:
        # 主库数据源
        master:
          type: ${spring.datasource.type}
          driverClassName: org.h2.Driver
          url: jdbc:h2:${spring.h2.file_path}${spring.h2.db_name}
      hikari:
        # 最大连接池数量
        maxPoolSize: 20
        # 最小空闲线程数量
        minIdle: 10
        # 配置获取连接等待超时的时间
        connectionTimeout: 30000
        # 校验超时时间
        validationTimeout: 5000
        # 空闲连接存活最大时间,默认10分钟
        idleTimeout: 600000
        # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
        maxLifetime: 1800000
        # 连接测试query(配置检测连接是否有效)
        connectionTestQuery: SELECT 1
        # 多久检查一次连接的活性
        keepaliveTime: 30000

初始化脚本

为了确保数据库初始化的顺利进行,请将您预先准备好的SQL初始化脚本放置于项目的resource的db文件夹中。这样设置后,系统将能够在启动时正确地识别并执行这些脚本,从而完成数据库的初始化工作。
初始化脚本
为了使项目能够顺利执行数据库初始化脚本,我们需要一个专门的工具来处理这一任务。
为此,我们将创建两个新的配置类:ApplicationContextRegisterH2DataInitConfig
这两个类将负责整合和配置项目所需的环境,确保脚本能够被正确执行。
ApplicationContextRegister 将用于注册和管理应用上下文,而 H2DataInitConfig 将专注于初始化H2数据库的数据。

package com.ray.h2Config;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

/**
 * 定义一个注册器策略类,方便后续加载资源文件
 * ApplicationContextAware是Spring框架提供的接口,也叫做spring上下文的增强器,在项目启动时执行,会被spring处理
 * 当一个bean实现了该接口,通过setApplicationContext方法可以直接获取spring容器中的所有bean
 */
@Component
public class ApplicationContextRegister implements ApplicationContextAware {

    private ApplicationContext applicationContext = null;

    /**
     * Spring容器启动时,会回调setApplicationContext方法,并传入ApplicationContext对象,之后就可对该对象进行操作。(例如获取spring容器中的所有bean)
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 提供一个方法,用于加载sql脚本文件
     * @param url sql文件位置
     */
    public Resource getResource(String url) {
        return this.applicationContext.getResource(url);
    }
}

package com.ray.h2Config;

import cn.hutool.core.collection.CollectionUtil;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.io.File;
import java.util.Arrays;
import java.util.List;

/**
 * 初始化h2数据库
 */
@Slf4j
@Service
// DataSource创建完后才初始化此类
@AutoConfigureAfter(DataSource.class)
public class H2DataInitConfig {

    @Value("${spring.h2.file_path}")
    private String filePath;

    // 初始化sql
    private static final String SCHEMA = "classpath:db/schema.sql";
    private static final List<String> INIT_DATA_LIST = Arrays.asList(
        "classpath:db/data.sql",
    );

    @Autowired
    DataSource dataSource;
    @Autowired
    ApplicationContextRegister applicationContextRegister;


    @PostConstruct
    public void init() throws Exception {
        // 文件锁,防止重复初始化
        File f = new File(filePath + File.separator + "h2_init.lock");
        if (!f.exists()) {
            log.info(">>> 开始初始化h2数据");
            boolean newFile = f.createNewFile();
            if (newFile && StringUtils.isNotBlank(SCHEMA)) {
                // 加载资源文件
                Resource schemaSql = applicationContextRegister.getResource(SCHEMA);
                // 手动执行SQL语句
                ScriptUtils.executeSqlScript(dataSource.getConnection(), schemaSql);
                // 初始化数据
                if (CollectionUtil.isNotEmpty(INIT_DATA_LIST)) {
                    for (String initData : INIT_DATA_LIST) {
                        Resource initDataSql = applicationContextRegister.getResource(initData);
                        ScriptUtils.executeSqlScript(dataSource.getConnection(), initDataSql);
                    }
                }
            }
            log.info(">>> 结束初始化h2数据");
        }
    }
}

结果

初次启动项目并完成数据初始化。

2024-12-13 16:32:01 [main] INFO  c.r.h2Config.H2DataInitConfig
 - >>> 开始初始化h2数据

... 省略sql

2024-12-13 16:32:01 [main] INFO  c.r.h2Config.H2DataInitConfig
 - >>> 结束初始化h2数据

执行完成


原文地址:https://blog.csdn.net/q343509740/article/details/144453379

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!