javascript
Spring Boot 简单集成 Liquibase
Liquibase 是一個用于跟蹤、管理和應用數據庫變化的開源的數據庫重構工具。它將所有數據庫的變化(包括結構和數據)都保存在 changelog文件中,便于版本控制,它的目標是提供一種數據庫類型無關的解決方案,通過執行 schema 類型的文件來達到遷移。
Liquibase 特性
Liquibase 具備如下特性:
- 支持幾乎所有主流的數據庫,如 MySQL, PostgreSQL, Oracle, Sql Server, DB2 等;
- 支持多開發者的協作維護;
- 日志文件支持多種格式,如 XML, YAML, JSON, SQL等;
- 支持上下文相關邏輯
- 生成數據庫變更文檔
- 支持多種運行方式,如命令行、Spring 集成、Maven 插件、Gradle 插件等。
更多詳情介紹,請查閱 Liquibase 官方文檔
Spring Boot 集成 Liquibase
添加依賴
因為 Spring Boot 已經內置支持整合 Liquibase,我們只需要在項目工程中引入 Liquibase 的依賴進行配置即可。
<dependency><groupId>org.liquibase</groupId><artifactId>liquibase-core</artifactId><version>3.6.3</version> </dependency> 復制代碼配置 application 文件
在 classpath 中配置 application.properties 或 application.yml 文件,
# 啟用liquibase liquibase.enabled=true # 存儲變化的文件(changelog)位置 liquibase.change-log=classpath:sample_change.sql # 檢查存儲變化的文件是否存在 liquibase.check-change-log-location=true # 分環境執行,若在 changelog 文件中設置了對應 context 屬性,則只會執行與 dev 對應值的 changeset liquibase.contexts=dev # 執行前首先刪除數據庫,默認 false。若設置為 true,則執行變更前,會先刪除目標數據庫,請謹慎 liquibase.dropFirst=false # 執行更新時將回滾 SQL 寫入的文件路徑 liquibase.rollback-file= # 如果使用工程已配置的 datasource 數據源,則以下三個數據庫連接參數可不配置 ## 訪問數據庫的連接地址 liquibase.url=jdbc:mysql://10.10.4.41:3306/test?useUnicode=true&characterEncoding=utf-8 # 訪問數據庫的用戶名 liquibase.user=test # 訪問數據庫的密碼 liquibase.password=test復制代碼注意:如果使用工程已配置的 datasource 數據源,則 liquibase.url、liquibase.user 和 liquibase.password這個三個參數可不配置,目標數據源即為工程已配置好的數據源。因為 Spring 會自動為 liquibase 獲取可用的數據源,詳情可查看這個類:org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration。
編寫存儲變更的 changelog 文件
目前 Liquibase 支持 XML、YAML、JSON 和 SQL 格式四種格式的 changelog 文件。為了方便和直觀,下面以基于 SQL 格式編寫 changelog 文件:sample_change.sql
--liquibase formatted sql--changeset zhouyi:1 -- 創建用戶表 CREATE TABLE `user` (`id` int(20) NOT NULL AUTO_INCREMENT,`name` varchar(50) NOT NULL,`age` int(10) NOT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;--rollback drop table user;--changeset zhouyi:2 insert into user(id, name, age) values(1,'張三',29); insert into user(id, name, age) values(2,'李四',20); 復制代碼啟動 Spring Boot 應用后,可以從日志看到輸出:
2019-03-27 13:13:16.439 [main] [] INFO liquibase.executor.jvm.JdbcExecutor.info:42 - DELETE FROM test.DATABASECHANGELOGLOCK 2019-03-27 13:13:16.442 [main] [] INFO liquibase.executor.jvm.JdbcExecutor.info:42 - INSERT INTO test.DATABASECHANGELOGLOCK (ID, `LOCKED`) VALUES (1, 0) 2019-03-27 13:13:16.506 [main] [] INFO liquibase.executor.jvm.JdbcExecutor.info:42 - SELECT `LOCKED` FROM test.DATABASECHANGELOGLOCK WHERE ID=1 2019-03-27 13:13:16.586 [main] [] INFO liquibase.lockservice.StandardLockService.info:42 - Successfully acquired change log lock 2019-03-27 13:13:16.697 [main] [] INFO liquibase.changelog.StandardChangeLogHistoryService.info:42 - Creating database history table with name: test.DATABASECHANGELOG 2019-03-27 13:13:16.700 [main] [] INFO liquibase.executor.jvm.JdbcExecutor.info:42 - CREATE TABLE test.DATABASECHANGELOG (ID VARCHAR(255) NOT NULL, AUTHOR VARCHAR(255) NOT NULL, FILENAME VARCHAR(255) NOT NULL, DATEEXECUTED datetime NOT NULL, ORDEREXECUTED INT NOT NULL, EXECTYPE VARCHAR(10) NOT NULL, MD5SUM VARCHAR(35) NULL, `DESCRIPTION` VARCHAR(255) NULL, COMMENTS VARCHAR(255) NULL, TAG VARCHAR(255) NULL, LIQUIBASE VARCHAR(20) NULL, CONTEXTS VARCHAR(255) NULL, LABELS VARCHAR(255) NULL, DEPLOYMENT_ID VARCHAR(10) NULL) 2019-03-27 13:13:17.570 [main] [] INFO liquibase.executor.jvm.JdbcExecutor.info:42 - SELECT COUNT(*) FROM test.DATABASECHANGELOG 2019-03-27 13:13:17.575 [main] [] INFO liquibase.changelog.StandardChangeLogHistoryService.info:42 - Reading from test.DATABASECHANGELOG 2019-03-27 13:13:17.579 [main] [] INFO liquibase.executor.jvm.JdbcExecutor.info:42 - SELECT * FROM test.DATABASECHANGELOG ORDER BY DATEEXECUTED ASC, ORDEREXECUTED ASC 2019-03-27 13:13:17.585 [main] [] INFO liquibase.executor.jvm.JdbcExecutor.info:42 - SELECT COUNT(*) FROM test.DATABASECHANGELOGLOCK 2019-03-27 13:13:17.678 [main] [] INFO liquibase.executor.jvm.JdbcExecutor.info:42 - CREATE TABLE `user` (`id` int(20) NOT NULL AUTO_INCREMENT,`name` varchar(50) NOT NULL,`age` int(10) NOT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 2019-03-27 13:13:17.935 [main] [] INFO liquibase.changelog.ChangeSet.info:42 - Custom SQL executed 2019-03-27 13:13:17.937 [main] [] INFO liquibase.changelog.ChangeSet.info:42 - ChangeSet classpath:sample_change.sql::1::zhouyi ran successfully in 297ms 2019-03-27 13:13:17.938 [main] [] INFO liquibase.executor.jvm.JdbcExecutor.info:42 - SELECT MAX(ORDEREXECUTED) FROM test.DATABASECHANGELOG復制代碼從數據庫中可以看到變化,首次運行新增了 3 張表,
其中DATABASECHANGELOG 和 DATABASECHANGELOGLOCK 表是 Liquibase 自動生成的,而 user 表是執行我們編寫的 changeset變更集后生成的,并且也已經執行了第 2 個變更集,插入了兩條數據。
SQL 格式的 changelogs 文件
SQL 格式的 changelog 文件使用 SQL 注釋作為元數據,為確保這個文件被 Liquibase 識別為 changelog文件,,SQL 文件必須以以下注釋開頭:
--liquibase formatted sql 復制代碼changeset 變更
SQL 格式的 changelog 文件中在變更的 SQL 前需要加上以下注釋,表示為一個 changeset變更集:
--changeset author:id attribute1:value1 attribute2:value2 [...] 復制代碼在之前的 sample_change.sql 文件中編寫了兩條 changeset (變更集),
變更集 changeset 是通過 author + id 的方式來保證唯一性,如以上 zhouyi:1 和 zhouyi:2 兩條表更集。
變更集提供以下屬性:
| stripComments | 設置為 true 可在執行之前刪除 SQL 中的任何注釋, 否則為 false。如果未設置, 則默認值為 true |
| splitStatements | |
| endDelimiter | 應用于語句結尾的分隔符。默認為“;”,也可以設置為“” |
| runAlways | 在每次運行時執行變更集, 即使之前已運行 |
| runOnChange | 在首次看到更改并每次更改變更集時執行更改 |
| context | 如果在運行時傳遞了特定上下文, 則執行更改。任何字符串都可以用于上下文名稱, 并且大小寫不敏感。 |
| logicalFilePath | 用于在創建變更集的唯一標識符時重寫文件名和路徑。移動或重命名更改日志時所必需。 |
| labels | 標簽是對變更集進行分類的通用方法集類似上下文, 但工作方式正好相反。如果不是在運行時定義一組上下文, 然后在變更集中定義一個匹配表達式, 而是在上下文中定義一組標簽, 在運行時定義一個匹配表達式。 |
| runInTransaction | 變更集是否應作為單個事務運行 (如果可能),默認值為 true。請注意此屬性,如果設置為 false, 并且通過運行包含多個語句的變更集部分發生錯誤, 則 liquibase 數據庫的 databasechangeloglock 表將處于無效狀態 |
| failOnError | 如果在執行變更集時發生錯誤, 遷移是否應返回失敗 |
| dbms | 要用于該變更集的數據庫的類型。當遷移步驟運行時, 它將根據此屬性檢查數據庫類型,如:oracle、mysql |
| logicalFilePath | 在數據庫 databasechangeloglock 中設置邏輯文件路徑, 而不是在執行 liquibase 的 sql 物理文件位置。 |
前置條件
可以為每個變更集指定先決條件。目前, 僅支持 SQL 檢查前置條件。
--preconditions onFail:HALT onError:HALT --precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM my_table 復制代碼回滾操作
變更集可能包括回滾變更集時要應用的語句。回滾聲明也是使用表注釋。
--rollback SQL STATEMENT 復制代碼例如在前面編寫的 changelog 文件中的第一個 changeset:
--changeset zhouyi:1 -- 創建用戶表 CREATE TABLE `user` (`id` int(20) NOT NULL AUTO_INCREMENT,`name` varchar(50) NOT NULL,`age` int(10) NOT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;--rollback drop table user; 復制代碼首先的變更的 SQL 含義是新建一個 user 表,回滾的 SQL 則表示刪除新建的 user 表。
Liquibase 最佳實踐
下面介紹可應用于項目的一些最佳實踐。
一個變更集只設置一次更改
盡可能地避免對一個變更集進行多次更改,以避免自動提交 SQL 語句而可能使數據庫處于非預期狀態。 如 --changeset zhouyi:1 變更集,只新建一張 user 表,后面不再修改該變更集,如果需要變更,可以新增一條變更集。
變更集的 ID
選擇適合您的方法。有的人是使用從 1 開始的序列號, 并且在更改日志中是唯一的,也有些人選擇一個描述性的名稱(例如:new-address-table)
總是考慮回滾
盡量嘗試以可以回滾的方式編寫變更集,如 --changeset zhouyi:1 變更集新建一個 user 表,在后面跟上回滾的 SQL, --rollback drop table user;
為變更集添加注釋
盡量為每一個變更集條目增加注釋,如 -- 創建用戶表
開發人員使用流程
- 使用您最喜歡的 IDE 或編輯器, 創建一個包含更改的新本地更改集;
- 運行 Liquibase 以執行新的變更集 (這將測試 SQL 代碼);
- 在應用程序代碼中執行相應的更改 (例如, Java 代碼);
- 測試驗證新的應用程序代碼以及數據庫更改;
- 提交變更集和應用程序代碼。
總結
以上是生活随笔為你收集整理的Spring Boot 简单集成 Liquibase的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基本数据与引用数据类型参数传递
- 下一篇: JavaScript字符串转数字的5种方