RoomのスキーマjsonからmermaidのER図を出力するGradle Pluginを作った

December 28, 2024

Roomにはスキーマのjsonファイルを出力する機能があるが、これを利用してテーブルのリレーションのER図をmermaidで生成するGradle Pluginを作った。

https://github.com/ntsk/room-schema-docs-gradle-plugin

mermaidのER図が記述されたmarkdownファイルを出力するのだが、GitHubではmermaid syntaxをプレビュー表示できる。 これにより本プラグインを利用して出力したファイルをgit管理しておくことで、チーム内でバージョン毎のテーブル構造の変遷を共有することができる。

モチベーション

作ろうと思った経緯として、自身が所属する開発チームがスケールするにつれて全ての開発差分をそれぞれのメンバーが把握することが困難となってきたことがあった。

開発しているプロダクトでは、オフライン対応のためにほぼ全てのレスポンスキャッシュをRoomで保持するようになっており、 並行して様々な機能を開発する中でテーブル構造も次々と変化していく。

ドキュメントを充実させるにしてもコストがかかる上、結局メンテされないドキュメントが残るケースが多かったことから、自動生成したかった。

使い方

README.md に記載の通りだが、プラグインを追加し、

plugins {
    id("jp.ntsk.room-schema-docs") version "1.0.0"
}

jsonファイルを出力しているディレクトリをschemaDirで、ER図を出力するディレクトリをoutputDirで指定する。

roomSchemaDocs {
    schemaDir = "$projectDir/schemas"
    outputDir = "$projectDir/schemas-docs"
}

ここまで設定したら、gradleタスクを実行すると各種スキーマのjsonファイルに応じたmarkdownファイルが生成される。

./gradlew generateRoomSchemaDocs

例えば、sample/schemas のようなjsonファイルから sample/schemas-docs のようなER図が記述されたmarkdownファイルを生成できる。

実装

mermaidには erDiagram を利用することでER図を記述できる syntax がある。

https://mermaid.js.org/syntax/entityRelationshipDiagram.html

下記のような記号で1対1、1対(0 or 1)、1対多、1対(0 or 多)の関係性を記述することで、 ER図を描画できる。

Value (left) Value (right) Meaning
o o Zero or one
| | Exactly one
}o o{ Zero or more (no upper limit)
}| |{ One or more (no upper limit)
erDiagram
    CUSTOMER ||--o{ ORDER : places
    CUSTOMER {
        string name
        string custNumber
        string sector
    }
    ORDER ||--|{ LINE-ITEM : contains
    ORDER {
        int orderNumber
        string deliveryAddress
    }
    LINE-ITEM {
        string productCode
        int quantity
        float pricePerUnit
    }

CUSTOMERstringnamestringcustNumberstringsectorORDERintorderNumberstringdeliveryAddressLINE-ITEMstringproductCodeintquantityfloatpricePerUnitplacescontains

CUSTOMERstringnamestringcustNumberstringsectorORDERintorderNumberstringdeliveryAddressLINE-ITEMstringproductCodeintquantityfloatpricePerUnitplacescontains

本プラグインでは、Kotlin SerializationでRoomが出力したjsonをparseし、このerDiagram syntaxで出力する。

このとき、Roomが出力するjsonのデータ構造をER図にすると下記の通りとなる。

RoomSchemaIntformatVersionDatabaseIntversionStringidentityHashEntity[]entitiesString[]setupQueriesEntityStringtableNameStringcreateSqlField[]fieldsPrimaryKeyprimaryKeyIndex[]indicesForeignKey[]foreignKeysFieldStringfieldPathStringcolumnNameStringaffinityBooleannotNullPrimaryKeyBooleanautoGenerateString[]columnNamesIndexStringnameBooleanuniqueString[]columnNamesString[]ordersStringcreateSqlForeignKeyStringtableStringonDeleteStringonUpdateString[]columnsString[]referencedColumnscontainscontainscontainshashashas

ER図の描画に必要な情報としては下記の通り。

  • テーブル名
  • カラム名・型
  • リレーション情報

テーブル名は、Entity.tableNameから取得。
カラム名は、Entity.fields.columnName、型は Entity.fields.affinity から取得できる。
リレーションは、Entity.foreignKeys.table からリレーション先を特定し、Index.unique からUNIQUE INDEXの有無やField.notNull からNOT NULL制約があるかをチェックすることで、1対1、1対(0 or 1)、1対多を判定してerDiagramのsyntaxを割り当てて書き出している。

今後

INDEXが張られているか、ON DELETE設定がどうなってるかも可視化できると便利そうなので、optionで追加したい。


© 2020-2024 ntsk.