在多租户场景下,利用liquibase实现数据库版本管理

摘要 :在SpringBoot的默认单一数据源下,liquibase能够进行数据库版本管理,如果是多租户情况下,则需要手动实现,本文主要介绍如何利用liquibase来实现多租户场景下的数据库版本管理。

简介

本文介绍的多租户场景,是多个用户数据库,使用的是同一个服务实例,然后通过header传递的tenant-id来区分具体使用哪一个数据库实例(如何实现多租户就不展开了,其他文章细说)。而数据库的版本管理,则需要统一进行管理,利用了SpringLiquibase类提供的管理能力,Hikari的数据库连接池。

配置说明

pom.xml文件

xml 复制代码
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-inline</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.liquibase</groupId>
            <artifactId>liquibase-core</artifactId>
        </dependency>
    </dependencies>

resource目录下的配置

mysql.xml

该文件配置数据库版本更新语句的目录

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">

    <!--  初始化表结构  -->
    <include file="/liquibase/mysql/*.sql"/>
</databaseChangeLog>

init.sql

sql 复制代码
--liquibase formatted sql

--changeset nise:202311201420
CREATE TABLE `USER` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`ID`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='用户';

LiquibaseDataSourceProperties 属性配置类

arduino 复制代码
@Data
public class LiquibaseDataSourceProperties {

    /** 驱动名称 */
    private String driverClassName;
    /** 链接地址 */
    private String jdbcUrl;
    /** 用户名 */
    private String username;
    /** 密码 */
    private String password;
    /** 数据库schema */
    private String schema;

}

schema说明

也可以理解为数据库的隔离一种方式,只不过每一种数据库的表现形式不一样

  • mysqlschema和数据库的名称一样,同一个名称下只有一个库。
  • oracleschema就是数据库名称,oracle一般采用服务名连接的。
  • kingbaseschema是数据库里面的具体空间名称,比如public,如果使用该方式实现多租户,则可以在同一个库里面通过命名空间区分。

LiquibaseService

管理服务,这里简单写一下,最好写到try cache finally中来关闭数据库连接,防止失败。

scss 复制代码
@Service
public class LiquibaseService {

    @Autowired
    private ResourceLoader resourceLoader;

    /**
     * 初始化数据库
     * @param properties
     */
    public void init(LiquibaseDataSourceProperties properties) throws Exception{
        HikariDataSource hikariDataSource = this.buildDataSource(properties);
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(hikariDataSource);
        liquibase.setResourceLoader(resourceLoader);
        //指定changelog的位置,这里使用的一个master文件引用其他文件的方式
        liquibase.setChangeLog("classpath*:liquibase/mysql.xml");
        liquibase.setShouldRun(true);
        liquibase.afterPropertiesSet();
        hikariDataSource.close();
    }

    private HikariDataSource buildDataSource(LiquibaseDataSourceProperties properties){
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setDriverClassName(properties.getDriverClassName());
        hikariDataSource.setJdbcUrl(properties.getJdbcUrl());
        hikariDataSource.setUsername(properties.getUsername());
        hikariDataSource.setPassword(properties.getPassword());
        hikariDataSource.setSchema(properties.getSchema());
        hikariDataSource.setMinimumIdle(1);
        hikariDataSource.setMaximumPoolSize(1);
        return hikariDataSource;
    }

}

服务调用

一般采用的是多数据源方式,或者采用从缓存中读取多租户的配置信息,然后初始化数据库;下面我就手动调用来模拟实现。

less 复制代码
@RestController
@RequestMapping(value = "liquibase")
public class LiquibaseController {

    @Autowired
    private LiquibaseService liquibaseService;

    @PostMapping(value = "init")
    public String init(@RequestBody LiquibaseDataSourceProperties properties) throws Exception{
        liquibaseService.init(properties);
        return "SUCCESS";
    }

}

结果

最终会生成两张数据库管理表DATABASECHANGELOGDATABASECHANGELOGLOCK和自己的业务表

相关推荐
栗豆包8 分钟前
w118共享汽车管理系统
java·spring boot·后端·spring·tomcat·maven
万亿少女的梦16821 分钟前
基于Spring Boot的网络购物商城的设计与实现
java·spring boot·后端
开心工作室_kaic2 小时前
springboot485基于springboot的宠物健康顾问系统(论文+源码)_kaic
spring boot·后端·宠物
0zxm2 小时前
08 Django - Django媒体文件&静态文件&文件上传
数据库·后端·python·django·sqlite
爱码少年6 小时前
springboot中责任链模式之简单应用
spring boot·责任链模式
苹果酱05676 小时前
「Mysql优化大师一」mysql服务性能剖析工具
java·vue.js·spring boot·mysql·课程设计
武昌库里写JAVA6 小时前
【MySQL】7.0 入门学习(七)——MySQL基本指令:帮助、清除输入、查询等
spring boot·spring·毕业设计·layui·课程设计
刘大辉在路上9 小时前
突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除
git·后端·gitlab·版本管理·源代码管理
追逐时光者11 小时前
免费、简单、直观的数据库设计工具和 SQL 生成器
后端·mysql