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(ES6),Java,AWSの大体のリソースです
コメントはやさしくお願いいたします^^
座右の銘は、「狭き門より入れ」「願わくは、我に七難八苦を与えたまえ」です^^
コメント