Spring Bootでliquibaseを使う方法(MySQL)
| Springバージョン |
|---|
| 2.1.1.RELEASE |
liquibase(リキベース)を使うとSpring Bootアプリケーションを実行する際にデータベースを作成して、さらにテーブルを作成したりデータ投入したり、テーブル削除したりと、マイグレーション管理ができるようです。
とりあえずデータベース作成して、テーブルをcreateしたかったのでliquibaseを使ってみました。
Spring Bootのスタータープロジェクトからliquibaseを選択します。
テーブルを作成するにはxml形式かyml形式でファイルを作成します。Spring Bootアプリケーション起動時に順次読み込んでテーブルを作成していってくれます。
前提として、ローカルPCにMySQLがインストールされていることとします。
build.gradleを以下のように修正します。これで起動時にliquibaseが実行されます。
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'
}
公式サイトを見るとどうもデフォルトのファイル名はdb.changelog-master.yamlのようです。
src\main\resources\db\db.changelog-master.yamlを配置します。
db.changelog-master.yaml
databaseChangeLog:
- include:
file: a.yaml
複数ある場合は改行してファイル名を指定していきます。
複数ファイルある場合のdb.changelog-master.yaml(デフォルトのファイル名です)の中身は以下のようになると思います。
databaseChangeLog:
- include:
file: a.yaml
- include:
file: b.yaml
上記ではa.yamlを読み込んだ後にb.yamlを読み込みます。
db.changelog-master.yamlでテーブル作成したりもできますし、上記のようにファイル分割することもできます。
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)
プロパティ名
MySQLにクエリパラメータでプロパティを設定することができます。
createDatabaseIfNotExist=true … データベースが存在しなければデータベースを作成する
application.properties
このファイルにMySQLの接続情報を記載しておきます。
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
spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.yamlでクラスパスとファイル名を変更できます。
Spring Bootアプリケーションを実行する
ではSpring Bootアプリケーションを実行してみます。sampledbというデータベースが作成され、databasechangelogテーブル、databasechangeloglockテーブル、personテーブルが作成されればOKです。
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)
テーブルにカラムを追加する
liquibaseはテーブルを作成しますが、そのあとテーブルのカラムが追加だったりした場合に新たにymlファイルを作成して、既存テーブルに対してALTER TABLE文を発行します。
ALTER TABLE文の実行方法は以下のようにします。
databaseChangeLog:
- changeSet:
id:11111112
comment: IDです
author: takahashi
changes:
- addColumn:
catalogName: スキーマ名
columns:
- column:
name: カラム名
remarks: 備考とかメモ
type: DATETIME
schemaName: スキーマ名
tableName: テーブル名
これで以下を実行するのと同じになります。MySQLではcatalogNameとschemaNameは省略可能です。
ALTER TABLE スキーマ名.テーブル名 ADD カラム名 DATETIME NULL;
カラムを複数追加したい場合は- column:の箇所を追加したい文だけ記述します。
テーブルのカラム名をリネームする
liquibaseはマイグレーションツールですが、簡単に言うとテーブル作成します。で、カラム名変わったのでカラム名を変更します。そのあとにテーブルが不要になったのでdropします、というような履歴ツールです。
今回はカラム名をリネームするymlを作成します。
databaseChangeLog:
- changeSet:
id:11111112
comment: IDです
author: takahashi
changes:
- renameColumn:
catalogName: スキーマ名
columnDataType:VARCHAR(10)
newColumnName: 新カラム名
oldColumnName: 旧カラム名
remarks: 備考とかメモ
schemaName: public
tableName: テーブル名
これでカラム名をリネームできるのですが、旧カラム名にnot null制約がついていた場合、制約が消えてしまいます。その場合は以下のように記述する必要があります。
databaseChangeLog:
- changeSet:
id:11111112
comment: IDです
author: takahashi
changes:
- renameColumn:
catalogName: スキーマ名
columnDataType:VARCHAR(10)
newColumnName: 新カラム名
oldColumnName: 旧カラム名
remarks: 備考とかメモ
schemaName: public
tableName: テーブル名
- addNotNullConstraint:
catalogName: スキーマ名
columnDataType: VARCHAR(10)
columnName: 新カラム名
defaultNullValue:
schemaName: public
tableName: テーブル名
テーブルのカラムの型を変更する
テーブルのカラムの型を変更するymlを作成します。以下ではintに変更しています。
databaseChangeLog:
- changeSet:
id:11111112
comment: IDです
author: takahashi
changes:
- modifyDataType:
catalogName: スキーマ名
columnName: 変更対象のカラム名
newDataType: int
schemaName: public
tableName: テーブル名
ユニークキーを付ける
ユニークキーを付けます。
databaseChangeLog:
- changeSet:
id:11111112
comment: IDです
author: takahashi
changes:
- addUniqueConstraint:
columnNames: キー1,キー2,キー3
constraintName: ユニーク制約名
deferrable: true
disable: true
initiallyDeferred: true
catalogName: スキーマ名
schemaName: public
tableName: テーブル名
以下と同様です。
ALTER TABLE テーブル名 ADD CONSTRAINT ユニーク制約名 UNIQUE (xx,yy,zz);
初期データをインサートする
liquibaseはテーブルを作成してくれますが、作成時はレコードがありません。
これは不便なのですが、もちろん初期レコードをインサートすることも可能です。
databaseChangeLog:
- changeSet:
id:11111113
comment: IDです
author: takahashi
changes:
- createTable:
tableName: sampleTbl
remarks: サンプルテーブルです
columns:
- column:
name: emp_id
remarks: 従業員ID
type: VARCHAR(10)
constrains:
nullable: false
- column:
name: emp_name
remarks: 従業員名
type: VARCHAR(30)
constrains:
nullable: false
- sql:
sql: INSERT INTO sampleTbl (emp_id, emp_name) VALUES ('1', '高橋')
- sql:
sql: INSERT INTO sampleTbl (emp_id, emp_name) VALUES ('2', 'デーミヤン')
これはテーブルを作成してから2件インサートしている例です。
DATABASECHANGELOGテーブルを触る
DATABASECHANGELOGテーブルは管理テーブルですが、何かの拍子でおかしくなればそのエラーが出ているymlファイルの1レコードだけを削除して、再度実行することができます。
この時、yamlに記載されているのがCREATE TABLEだったら、あらかじめDROP TABLEしておくなどの対応は必要です。
DATABASECHANGELOGLOCKテーブルは触ることはない気がします。
liquibase(MySQL)でパーティショニングする
liquibase(MySQL)でパーティショニングするには、sqlでalter文を使うしか方法がありません。フォーラム
postgreSQLは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));
MySQLでは以下のようにsqlで記述する必要があります。
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));

KHI入社して退社。今はCONFRAGEで正社員です。関西で140-170/80~120万から受け付けております^^
得意技はJS(ES20xx),Java,AWSの大体のリソースです
コメントはやさしくお願いいたします^^
座右の銘は、「狭き門より入れ」「願わくは、我に七難八苦を与えたまえ」です^^


コメント