How to use liquibase with Spring Boot (MySQL)
| Spring Version |
|---|
| 2.1.1.RELEASE |
It seems that liquibase can be used to create a database when running a Spring Boot application, and also to create tables, populate data, delete tables, etc., to manage migration.
For now, I used liquibase because I wanted to create a database and CREATE tables.
Select liquibase from the Spring Boot starter project.
To create tables, you can create files in xml or yml format, which will be read and created one by one when the Spring Boot application starts.
We assume that MySQL is installed on the local PC.
Modify build.gradle as follows Now liquibase will be executed at startup.
buildscript {
ext {
springBootVersion = '2.1.1.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.liquibase:liquibase-core' // 追加
runtimeOnly 'mysql:mysql-connector-java'
compileOnly 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
The default file name seems to be db.changelog-master.yaml, according to the official site.
Place src\main\resources\db\db.changelog-master.yaml
db.changelog-master.yaml
databaseChangeLog:
- include:
file: a.yaml
If there is more than one file, we will specify the file name with a new line.
The contents of db.changelog-master.yaml (which is the default file name) in the case of multiple files would be as follows.
databaseChangeLog:
- include:
file: a.yaml
- include:
file: b.yaml
In the above, b.yaml is read after a.yaml is read.
You can create tables in db.changelog-master.yaml, or split files as shown above.
Here is an example of a.yaml.
databaseChangeLog:
- changeSet:
id: 1
author: confrage
changes:
- createTable:
tableName: person
columns:
- column:
name: id
type: int
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: firstname
type: varchar(50)
- column:
name: lastname
type: varchar(50)
constraints:
nullable: false
- column:
name: state
type: char(2)
Property Name
You can set properties in MySQL with query parameters
createDatabaseIfNotExist=true … create database if database does not exist
application.properties
This file should contain the MySQL connection information.
spring.datasource.url=jdbc:mysql://localhost:3306/sampledb?serverTimezone=UTC&createDatabaseIfNotExist=true spring.datasource.username=root spring.datasource.password=system spring.jpa.database=MYSQL spring.liquibase.change-log=classpath:db/db.changelog-master.yaml
You can change the classpath and file name in spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.yaml.
Running a Spring Boot application
Now let’s run the Spring Boot application, and you should see the database sampledb created, and the databasechangelog table, databasechangeloglock table, and person table created.
mysql> desc person; +-----------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | firstname | varchar(50) | YES | | NULL | | | lastname | varchar(50) | NO | | NULL | | | state | char(2) | YES | | NULL | | +-----------+-------------+------+-----+---------+----------------+ 4 rows in set (0.03 sec)
Adding columns to a table
liquibase creates a table, but then creates a new YML file and issues an ALTER TABLE statement against the existing table when additional columns are added to the table.
The ALTER TABLE statement is executed as follows
databaseChangeLog:
- changeSet:
id:11111112
comment: ID
author: takahashi
changes:
- addColumn:
catalogName: schema name
columns:
- column:
name: column name
remarks: Remarks and notes
type: DATETIME
schemaName: schema name
tableName: table name
This is equivalent to doing the following, except that catalogName and schemaName are optional in MySQL.
ALTER TABLE schema.table_name ADD カラム名 DATETIME NULL;
If you want to add more than one column, write only the sentence you want to add in the – column: field.
Rename a table column name
LIQUIBASE is a migration tool, but simply put, it creates tables. Then, the column name is changed, so the column name is changed. After that, the table is no longer needed, so it is dropped, and so on.
In this case, we will create a yml to rename column names.
databaseChangeLog:
- changeSet:
id:11111112
comment: ID
author: takahashi
changes:
- renameColumn:
catalogName: schema name
columnDataType:VARCHAR(10)
newColumnName: New column name
oldColumnName: Old column name
remarks: Remarks and notes
schemaName: public
tableName: table name
This will rename the column name, but if the old column name had a not null constraint, the constraint will disappear. In that case, you need to write as follows
databaseChangeLog:
- changeSet:
id:11111112
comment: ID
author: takahashi
changes:
- renameColumn:
catalogName: schema name
columnDataType:VARCHAR(10)
newColumnName: New column name
oldColumnName: Old column name
remarks: Remarks and notes
schemaName: public
tableName: table name
- addNotNullConstraint:
catalogName: schema name
columnDataType: VARCHAR(10)
columnName: New column name
defaultNullValue:
schemaName: public
tableName: table name
Change the type of a table column
Create a yml that changes the type of a table column. In the following, we change it to int.
databaseChangeLog:
- changeSet:
id:11111112
comment: IDです
author: takahashi
changes:
- modifyDataType:
catalogName: schema name
columnName: Column name to be changed
newDataType: int
schemaName: public
tableName: table name
set a unique key
Attach a unique key.
databaseChangeLog:
- changeSet:
id:11111112
comment: IDです
author: takahashi
changes:
- addUniqueConstraint:
columnNames: Key 1, Key 2, Key 3
constraintName: unique constraint name
deferrable: true
disable: true
initiallyDeferred: true
catalogName: schema name
schemaName: public
tableName: table name
以下と同様です。
ALTER TABLE table name ADD CONSTRAINT unique constraint name UNIQUE (xx,yy,zz);
Insert initial data
LIQUIBASE creates the table, but there are no records when it is created.
This is inconvenient, but of course it is possible to insert initial records.
databaseChangeLog:
- changeSet:
id:11111113
comment: ID
author: takahashi
changes:
- createTable:
tableName: sampleTbl
remarks: Sample table.
columns:
- column:
name: emp_id
remarks: Employee ID
type: VARCHAR(10)
constrains:
nullable: false
- column:
name: emp_name
remarks: Employee Name
type: VARCHAR(30)
constrains:
nullable: false
- sql:
sql: INSERT INTO sampleTbl (emp_id, emp_name) VALUES ('1', 'takahashi')
- sql:
sql: INSERT INTO sampleTbl (emp_id, emp_name) VALUES ('2', 'demien')
This is an example of creating a table and then inserting two inserts.
Modify the DATABASECHANGELOG table
The DATABASECHANGELOG table is a management table, but if something goes wrong, you can delete only one record in the yml file that is causing the error and run it again.
At this time, if CREATE TABLE is listed in the yaml file, it is necessary to DROP TABLE the table in advance.
I don’t think the DATABASECHANGELOGLOCK table should be modified.
Partitioning with liquibase (MySQL)
The only way to partition in liquibase (MySQL) is to use an ALTER statement in sql.
postgreSQL seems to support modifySql.
modifySql:
dbms: postgresql
append value: PARTITION BY RANGE COLUMNS(borned) (PARTITION p0 VALUES LESS THAN ('2000-01-01 00:00:00'),PARTITION p1 VALUES LESS THAN (MAXVALUE));
In MySQL, it must be written in sql as follows.
databaseChangeLog:
- changeSet:
id: 1
author: takahashi
changes:
- createTable:
tableName: person
columns:
- column:
name: id
type: int
constraints:
nullable: false
- column:
name: firstname
type: varchar(50)
- column:
name: lastname
type: varchar(50)
constraints:
nullable: false
- column:
name: borned
type: datetime
sql: |
alter table person
PARTITION BY RANGE COLUMNS(borned)
(PARTITION p0 VALUES LESS THAN ('2000-01-01 00:00:00'),
PARTITION p1 VALUES LESS THAN (MAXVALUE));




コメント