Liquibase and Flyway are two mature, excellent, open source/commercial versions of database version management tools. In view of the limitations of Flyway's community version on Oracle database support, boot-admin chose to integrate Liquibase to provide database version management capability support.
The open source version of Liquibase uses the Apache 2.0 protocol.
When is Liquibase suitable?
- When your project is upgraded, there is a high probability that the database will also need to be upgraded simultaneously. Liquibase will automatically scan the database migration file (changeSet) and compare the version number of the migration file with the version number in the history table (changelog). , skip the executed migration files, execute the unexecuted new version migration files sequentially, and finally match the database and code versions;
- When multiple people collaborate on a project, the system source code can be synchronized using git, and the database synchronization can be guaranteed by liquibase;
- Use liquibase to easily compare the differences between two databases;
- Using liquibase also supports database version rollback.
What are the advantages of Liquibase?
- Configuration files support SQL, XML, JSON or YAML;
- Compatible with 14 mainstream databases such as oracle, mysql, etc., and supports smooth migration;
- Version control is performed sequentially;
- You can use context to control when, where and how SQL is executed;
- Ability to have if/then logic in applications;
- Support schema changes;
- Automatically generate sql statements based on the configuration file for preview;
- Migration can be performed repeatedly;
- Plug-in expandable;
- Can be rolled back;
- Support multi-tenant in schema mode;
- Ability to have the same change description on multiple database types;
- Generated database history document;
- Ability to easily specify more complex multi-statement changes.
Integration points
boot-admin is a SaaS backend management framework that adopts front-end and back-end separation mode and is based on Spring Cloud microservice architecture. The system has built-in 6 functional modules: basic management, authority management, operation management, definition management, code generator and office management. It integrates distributed transaction Seata, workflow engine Flowable, business rules engine Drools, background job scheduling framework Quartz, etc., technology stack Including Mybatis-plus, Redis, Nacos, Seata, Flowable, Drools, Quartz, SpringCloud, Springboot Admin Gateway, Liquibase, jwt, Openfeign, I18n, etc.
Project source code warehouse github
project source code warehouse gitee
Introduce Maven dependencies
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
Add configuration
spring:
liquibase:
enabled: true
change-log: classpath:liquibase/master.xml
Create master.xml
Create the folder liquibase under resources and create the file master.xml
<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">
<includeAll path="liquibase/changelogs/" relativeToChangelogFile="false"/>
</databaseChangeLog>
Create two folders, changelogs and sql, under the liquibase folder, as shown in the following figure:
Write the database change unit changeSet
Create a changeSet file under resources\liquibase\changelogs. It is recommended to have one xml file per month. The file name format is: [changelog-year+month.xml], such as: changelog-202304.xml. Examples of common operations
:
Create table
<changeSet author="admin (generated)" id="00001-9">
<createTable remarks="行政区划表" tableName="TB_ADM_DIV">
<column name="GUID" remarks="主键" type="NVARCHAR2(38)">
<constraints nullable="false" primaryKey="true" primaryKeyName="PK_TB_ADM_DIV"/>
</column>
<column name="ADM_DIV_CODE" remarks="行政区划代码" type="NVARCHAR2(12)">
<constraints nullable="false"/>
</column>
<column name="ADM_DIV_NAME" remarks="行政区划名称" type="NVARCHAR2(100)">
<constraints nullable="false"/>
</column>
<column name="CREATE_BY" remarks="记录创建者" type="NVARCHAR2(100)">
<constraints nullable="false"/>
</column>
<column name="CREATE_TIME" remarks="记录创建时间" type="${type.datetime}">
<constraints nullable="false"/>
</column>
<column name="MODIFY_BY" remarks="记录最后修改者" type="NVARCHAR2(100)">
<constraints nullable="false"/>
</column>
<column name="MODIFY_TIME" remarks="记录最后修改时间" type="${type.datetime}">
<constraints nullable="false"/>
</column>
<column defaultValueComputed="${now}" name="DATESTAMP" remarks="时间戳" type="${type.datetime}">
<constraints nullable="false"/>
</column>
<column name="ENABLED" remarks="启用状态;ENABLED" type="NVARCHAR2(1)">
<constraints nullable="false"/>
</column>
<column name="DELETED" remarks="删除状态;DELETED" type="NVARCHAR2(1)">
<constraints nullable="false"/>
</column>
<column name="VERSION" remarks="乐观锁" type="${type.int}">
<constraints nullable="false"/>
</column>
<column name="REMARKS" remarks="备注" type="NVARCHAR2(900)"/>
<column name="TENANT_ID_" remarks="租户ID" type="NVARCHAR2(38)">
<constraints nullable="false"/>
</column>
<column name="PARENT_GUID" remarks="父级GUID" type="NVARCHAR2(38)">
<constraints nullable="false"/>
</column>
<column name="LEAF" remarks="是否末级;YESNO" type="NVARCHAR2(1)">
<constraints nullable="false"/>
</column>
<column name="SORT" remarks="顺序号" type="${type.int}">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
Add table fields
<changeSet author="admin" id="00002-1">
<addColumn tableName="TB_ADM_DIV">
<column name="EXT" remarks="扩展" type="VARCHAR(64)"/>
</addColumn>
</changeSet>
Delete table field
<changeSet author="admin" id="00002-2">
<dropColumn tableName="TB_ADM_DIV" columnName="EXT"/>
</changeSet>
Modify table field description
<changeSet author="admin" id="00002-3">
<setColumnRemarks tableName="TB_ADM_DIV" columnName="EXT" remarks="扩展字段"/>
</changeSet>
Modify table field type
<changeSet author="admin" id="00002-4">
<modifyDataType tableName="TB_ADM_DIV" columnName="EXT" newDataType="VARCHAR2(2000)"/>
</changeSet>
Create view
<changeSet author="admin (generated)" id="00001-1" dbms="oracle">
<createView fullDefinition="true" remarks="表和视图" viewName="V_TABLES_MASTER">
CREATE OR REPLACE FORCE VIEW V_TABLES_MASTER (TABLE_SCHEMA, TABLENAME, TABLETYPE, COMMENTS, TENANT_ID_) AS
select SYS_CONTEXT('USERENV','CURRENT_SCHEMA') TABLE_SCHEMA,
t.tname tableName,
tabtype tabletype,
f.comments comments,
'DEMO' TENANT_ID_
from tab t
inner join user_tab_comments f
on t.tname = f.table_name
where tname != 'DATABASECHANGELOG'
and tname != 'DATABASECHANGELOGLOCK'
and tname != 'UNDO_LOG'
</createView>
</changeSet>
<changeSet author="37514 (generated)" id="00000-2" dbms="mysql">
<createView fullDefinition="true" remarks="表和视图" viewName="V_TABLES_MASTER">
CREATE OR REPLACE VIEW V_TABLES_MASTER AS
SELECT
TABLE_SCHEMA,
TABLE_NAME AS TABLENAME,
case when table_type='BASE TABLE' then 'TABLE' ELSE table_type END AS TABLETYPE,
TABLE_COMMENT AS COMMENTS,
'DEMO' TENANT_ID_
FROM
information_schema.`TABLES`
WHERE table_name != 'databasechangeloglock' AND TABLE_NAME != 'databasechangelog' AND TABLE_NAME != 'undo_log'
</createView>
</changeSet>
Compatible with Oracle and Mysql configuration
<property name="type.datetime" value="date" dbms="oracle"/>
<property name="type.datetime" value="timestamp" dbms="mysql"/>
<property name="type.int" value="NUMBER(*, 0)" dbms="oracle"/>
<property name="type.int" value="INT" dbms="mysql"/>
<property name="type.decimal" value="NUMBER(*, 2)" dbms="oracle"/>
<property name="type.decimal" value="DECIMAL" dbms="mysql"/>
<property name="now" value="SYSDATE" dbms="oracle"/>
<property name="now" value="now()" dbms="mysql,h2"/>
<property name="autoIncrement" value="true" dbms="mysql,h2,postgresql,oracle"/>
<property name="amount" value="decimal(20,2)"/>
<property name="uuid" value="sys_guid()" dbms="oracle"/>
<property name="uuid" value="UUID()" dbms="mysql"/>
Execute SQL file
<changeSet id="20000820-003" author="Administrator" dbms="oracle">
<sqlFile dbms="oracle" path="classpath:/liquibase/sql/seata-undo_log-oracle.sql" />
</changeSet>
<changeSet id="20000820-003" author="Administrator" dbms="mysql">
<sqlFile dbms="mysql" path="classpath:/liquibase/sql/seata-undo_log-mysql.sql" />
</changeSet>
The corresponding sql file needs to be placed in the specified folder.
Liquibase changeSet common command list
add
Label | describe |
---|---|
addAutoIncrement | Convert an existing column to increment |
addColunm | Add column |
addDefaultValue | Add default value to existing column |
addForeignKeyConstraint | Add foreign key constraints to existing columns |
addLookupTable | Create tables related by foreign keys |
addNotNullConstraint | Add a non-null constraint to an existing column |
addPrimaryKey | Add primary key constraints to existing columns |
ddUniqueConstraint | Add primary key constraints to existing columns |
create
Label | describe |
---|---|
createIndex | Create index |
createProcedure | Create stored procedure |
createSequence | Create sequence |
createTable | Create table |
createView | Create view |
drop
Label | describe |
---|---|
dropAllForeignKeyConstraints | Delete all foreign key constraints |
dropColumn | Delete column |
dropDefaultValue | Remove default settings |
dropForeignKeyConstraint | Delete a foreign key constraint on a column |
dropNotNullConstraint | Remove non-null constraints |
dropIndex | Delete index |
dropSequence | Delete constraints |
dropProcedure | Delete stored procedure |
dropPrimaryKey | Delete primary key |
dropTable | Delete table |
dropUniqueConstraint | Remove unique constraint |
dropView | Delete view |
rename
Label | describe |
---|---|
renameColumn | double named sequence |
renameSequence | double naming order |
renameTable | Rename table |
renameView | Rename view |
sql
Label | describe |
---|---|
sql | Native SQL |
sqlFile | Import SQL files |
other
Label | describe | Label | describe |
---|---|---|---|
alterSequence | Modify sequence | customChange | To customize the change type, you need to implement the liquibase.change.custom.CustomSqlChange and liquibase.change.custom.CustomTaskChange interfaces yourself. |
delete | delete data | empty | No operation |
executeCommand | Execute system commands such as mysqldump | insert | Insert data |
loadData | Load csv file into existing table | loadUpdateData | Load the csv file into an existing table, but it will be judged whether it exists and updated, otherwise it will be added |
mergeColumns | Combine the values of two columns together and store them in a new column | modifyDataType | Modify column data type |
output | Log a message and continue execution | setColumnRemarks | Add notes to columns |
setTableRemarks | Add notes to the table | stop | Stop Liquibase via message |
tagDatabase | Apply labels to database for future rollback | update | update data |