Spring Boot 整合 Liquibase 完整案例
项目结构
spring-boot-liquibase-demo/
├── pom.xml
├── src/main/java/com/example/liquibase/
│ ├── LiquibaseApplication.java
│ ├── controller/
│ │ └── UserController.java
│ ├── entity/
│ │ └── User.java
│ ├── mapper/
│ │ └── UserMapper.java
│ └── service/
│ └── UserService.java
├── src/main/resources/
│ ├── application.yml
│ ├── db/
│ │ ├── changelog/
│ │ │ └── db.changelog-master.yaml
│ │ └── changelog/
│ │ ├── 001-create-user-table.yaml
│ │ ├── 002-add-column.yaml
│ │ └── 003-insert-data.yaml
│ ├── mapper/
│ │ └── UserMapper.xml
│ └── schema.sql (可选,用于初始化数据库)
└── src/test/java/com/example/liquibase/
└── LiquibaseApplicationTests.java
pom.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-boot-liquibase-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-liquibase-demo</name>
<description>Spring Boot Liquibase 整合案例</description>
<properties>
<java.version>17</java.version>
<mybatis-plus.version>3.5.5</mybatis-plus.version>
<mysql.version>8.0.33</mysql.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot JPA (可选,如果使用JPA) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MyBatis Plus (如果使用MyBatis) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Liquibase 核心依赖 -->
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<!-- Liquibase 额外支持 (YAML格式) -->
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- H2 内存数据库 (用于测试,可选) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<!-- Liquibase Maven Plugin -->
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>4.27.0</version>
<configuration>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
</configuration>
</plugin>
</plugins>
</build>
</project>
主应用类
package com.example.liquibase;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.example.liquibase.mapper")
public class LiquibaseApplication {
public static void main(String[] args) {
SpringApplication.run(LiquibaseApplication.class, args);
}
}
application.yml 配置
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/liquibase_demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
# Liquibase 配置
liquibase:
enabled: true
change-log: classpath:db/changelog/db.changelog-master.yaml
# 生成的数据表前缀
database-change-log-lock-table: DATABASECHANGELOGLOCK
database-change-log-table: DATABASECHANGELOG
# 每次启动时强制更新
drop-first: false
# 是否启用默认的 schema
default-schema: public
# JPA 配置(如果使用)
jpa:
hibernate:
ddl-auto: none # 让 Liquibase 管理数据库结构
show-sql: true
properties:
hibernate:
format_sql: true
# MyBatis Plus 配置(如果使用)
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.liquibase.entity
configuration:
map-underscore-to-camel-case: true
logging:
level:
org.liquibase: INFO
com.example.liquibase: DEBUG
Liquibase Changelog 文件
1 主 Changelog 文件 db.changelog-master.yaml
databaseChangeLog:
# 检查数据库类型,如果是 H2 则使用对应的种类型
- preConditions:
- runningAs:
username: root
# 包含各个子 changelog 文件
- include:
file: classpath:db/changelog/001-create-user-table.yaml
- include:
file: classpath:db/changelog/002-add-column.yaml
- include:
file: classpath:db/changelog/003-insert-data.yaml
- include:
file: classpath:db/changelog/004-add-index.yaml
2 创建用户表 001-create-user-table.yaml
databaseChangeLog:
- changeSet:
id: 001-create-user-table
author: admin
changes:
- createTable:
tableName: user
remarks: 用户表
columns:
- column:
name: id
type: BIGINT
autoIncrement: true
constraints:
primaryKey: true
nullable: false
primaryKeyName: pk_user_id
remarks: 主键ID
- column:
name: username
type: VARCHAR(50)
constraints:
nullable: false
unique: true
remarks: 用户名
- column:
name: email
type: VARCHAR(100)
constraints:
nullable: false
unique: true
remarks: 邮箱
- column:
name: password
type: VARCHAR(255)
constraints:
nullable: false
remarks: 密码
- column:
name: phone
type: VARCHAR(20)
remarks: 手机号
- column:
name: status
type: TINYINT
defaultValueNumeric: 1
remarks: 状态(1-正常,0-禁用)
- column:
name: created_at
type: TIMESTAMP
defaultValueComputed: CURRENT_TIMESTAMP
remarks: 创建时间
- column:
name: updated_at
type: TIMESTAMP
defaultValueComputed: CURRENT_TIMESTAMP
remarks: 更新时间
3 添加新列 002-add-column.yaml
databaseChangeLog:
- changeSet:
id: 002-add-column
author: admin
changes:
- addColumn:
tableName: user
columns:
- column:
name: avatar_url
type: VARCHAR(500)
remarks: 头像URL
- column:
name: age
type: INT
remarks: 年龄
- addNotNullConstraint:
tableName: user
columnName: age
columnDataType: INT
defaultNullValue: 0
constraintName: ck_user_age_not_null
4 插入初始数据 003-insert-data.yaml
databaseChangeLog:
- changeSet:
id: 003-insert-data
author: admin
changes:
- insert:
tableName: user
columns:
- column: { name: username, value: "admin" }
- column: { name: email, value: "admin@example.com" }
- column: { name: password, value: "$2a$10$E0DqKkXrHGzL7lUaBmHnUeGdK5C3wjJYr9O1zNmF8bVkFwYxUyTiW" }
- column: { name: phone, value: "13800138000" }
- column: { name: status, valueNumeric: 1 }
- column: { name: avatar_url, value: "https://example.com/avatar.png" }
- column: { name: age, valueNumeric: 30 }
- insert:
tableName: user
columns:
- column: { name: username, value: "test_user" }
- column: { name: email, value: "test@example.com" }
- column: { name: password, value: "$2a$10$E0DqKkXrHGzL7lUaBmHnUeGdK5C3wjJYr9O1zNmF8bVkFwYxUyTiW" }
- column: { name: phone, value: "13900139000" }
- column: { name: status, valueNumeric: 1 }
- column: { name: avatar_url, value: null }
- column: { name: age, valueNumeric: 25 }
5 添加索引 004-add-index.yaml
databaseChangeLog:
- changeSet:
id: 004-add-index
author: admin
changes:
- createIndex:
tableName: user
indexName: idx_user_email
unique: true
columns:
- column:
name: email
- createIndex:
tableName: user
indexName: idx_user_status
unique: false
columns:
- column:
name: status
实体类(使用 JPA)
package com.example.liquibase.entity;
import jakarta.persistence.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "user")
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false, unique = true)
private String email;
@Column(nullable = false)
private String password;
private String phone;
private Integer status;
@Column(name = "avatar_url")
private String avatarUrl;
private Integer age;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
updatedAt = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
}
Controller 和 Service
package com.example.liquibase.controller;
import com.example.liquibase.entity.User;
import com.example.liquibase.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> getAllUsers() {
return userService.findAll();
}
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.save(user);
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.save(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteById(id);
}
}
package com.example.liquibase.service;
import com.example.liquibase.entity.User;
import com.example.liquibase.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> findAll() {
return userRepository.findAll();
}
public User findById(Long id) {
return userRepository.findById(id).orElse(null);
}
public User save(User user) {
return userRepository.save(user);
}
public void deleteById(Long id) {
userRepository.deleteById(id);
}
}
Liquibase 常用配置和属性文件
1 liquibase.properties 文件
# 数据库连接配置 url=jdbc:mysql://localhost:3306/liquibase_demo username=root password=your_password # Liquibase 配置 changeLogFile=classpath:db/changelog/db.changelog-master.yaml # 日志级别 logLevel=INFO # 上下文 contexts=dev,prod # 标签 labels=test
2 不同环境配置
# application-dev.yml
spring:
liquibase:
contexts: dev
change-log: classpath:db/changelog/db.changelog-master.yaml
# application-prod.yml
spring:
liquibase:
contexts: prod
change-log: classpath:db/changelog/db.changelog-prod.yaml
高级功能示例
1 使用 SQL 格式的 changelog
005-custom-sql.yaml:

databaseChangeLog:
- changeSet:
id: 005-custom-sql
author: admin
changes:
- sql:
sql: |
ALTER TABLE user
ADD COLUMN last_login_date TIMESTAMP;
- sqlFile:
path: classpath:db/sql/update-user.sql
splitStatements: true
stripComments: true
2 使用存储过程和视图
006-create-view.yaml:
databaseChangeLog:
- changeSet:
id: 006-create-view
author: admin
changes:
- createView:
viewName: v_user_info
selectQuery: |
SELECT u.id, u.username, u.email, u.status
FROM user u
WHERE u.status = 1
replaceIfExists: true
测试配置(使用 H2 内存数据库)
# src/test/resources/application-test.yml
spring:
datasource:
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
username: sa
password:
driver-class-name: org.h2.Driver
liquibase:
enabled: true
change-log: classpath:db/changelog/db.changelog-master.yaml
jpa:
hibernate:
ddl-auto: none
database-platform: org.hibernate.dialect.H2Dialect
十一、Maven 命令
# 运行 Liquibase 命令 mvn liquibase:status # 查看变更状态 mvn liquibase:update # 执行变更 mvn liquibase:rollback # 回滚变更 mvn liquibase:validate # 验证 changelog mvn liquibase:clearCheckSums # 清除校验和 # 启动应用 mvn spring-boot:run # 打包并启动 mvn clean package java -jar target/spring-boot-liquibase-demo-0.0.1-SNAPSHOT.jar
十二、最佳实践建议
-
使用规范化命名:changelog 文件按日期或序号命名,如
20240101-001-create-table.yaml -
只增不改:已经执行过的 changeSet 不要修改内容,如果要修改请创建新的 changeSet
-
使用上下文和环境:通过
contexts和labels控制不同环境执行的 changelog -
添加验证条件:使用
preConditions和validate保证数据一致性 -
使用变量和模板:可以通过 语法使用环境变量
-
版本控制:将 changelog 文件纳入版本控制,保持变更历史清晰
-
测试:在测试环境先行验证 changelog 脚本的正确性
-
文档:每个 changeSet 添加清晰的
remarks说明
databaseChangeLog:
- changeSet:
id: 20240101-001-create-user-table
author: admin
remarks: 创建用户表
changes:
- createTable: ...
这个案例展示了 Spring Boot 与 Liquibase 的完整整合方案,包括数据库版本管理、自动更新、回滚等核心功能,记得根据实际项目需求调整配置和目录结构。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播