シリーズ総括

このシリーズで実装したものを振り返ります。

PART実装内容使用ライブラリ
03ASTを走査してSQL文字列を抽出JavaParser
04SQL文字列からテーブル名・操作種別を取得JSqlParser
05クラス横断でCRUD行列を構築Java標準
06Markdown・Mermaid・PlantUMLで出力Java標準
07サンプルプロジェクトで動作確認

フレームワーク非依存で動作し、DBやアプリケーションを起動せずにCRUD図を生成できる実用的なツールが完成しました。

静的解析の限界

動的SQL(StringBuilder)
sb.append("SELECT").append("FROM ").append(tableName) のように実行時にSQLを組み立てるコードは検出できない。
外部ファイルのSQL
XMLやプロパティファイルに書かれたSQL(MyBatisのMapper XMLなど)はJavaパーサーでは取得できない。
変数経由のSQL
別クラスから渡された文字列変数の値が SQL の場合、追跡するためにはデータフロー解析が必要でスコープ外。
方言非対応
Oracle固有の MERGE INTOCONNECT BY など、JSqlParserが対応していない方言は例外になる。

限界への対処法

課題対処法
動的SQL(Builder/Format) 部分的なSQL断片("FROM users" など)にもパターンマッチを適用し、テーブル名だけ取り出す簡易フォールバック実装を追加する
外部XMLのSQL MyBatisのMapper XML専用パーサーを別途作成し、同じ CrudMatrixAggregator に追加する
JSqlParser非対応方言 CCJSqlParserUtil.parse() 失敗時に正規表現フォールバックを試みる
高精度が必要な箇所 p6spy等の動的解析と組み合わせてハイブリッドで対応する

Gradleタスクへの組み込み

Groovy — build.gradle にカスタムタスク追加
// build.gradle
task generateCrudDiagram(type: JavaExec) {
    description = 'CRUD図を生成してdocs/に出力します'
    group       = 'documentation'

    classpath = sourceSets.main.runtimeClasspath
    mainClass  = 'com.example.tools.Main'

    // 引数: [srcRoot, outputDir]
    args = [
        project.file('src/main/java').absolutePath,
        project.file('docs').absolutePath
    ]
}

// buildタスクに含めない場合は依存関係不要
// 含める場合:
// compileJava.finalizedBy generateCrudDiagram
Shell — 実行コマンド
./gradlew generateCrudDiagram

Mavenプラグインへの組み込み

XML — pom.xml exec-maven-plugin 設定
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>3.3.0</version>
    <executions>
        <execution>
            <id>generate-crud-diagram</id>
            <phase>verify</phase>
            <goals><goal>java</goal></goals>
            <configuration>
                <mainClass>com.example.tools.Main</mainClass>
                <arguments>
                    <argument>${project.basedir}/src/main/java</argument>
                    <argument>${project.basedir}/docs</argument>
                </arguments>
            </configuration>
        </execution>
    </executions>
</plugin>

CI/CD統合のヒント

YAML — GitHub Actions 例
name: Update CRUD Diagram

on:
  push:
    paths:
      - 'src/main/java/**'

jobs:
  crud-diagram:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          java-version: '21'
          distribution: 'temurin'
      - name: Generate CRUD Diagram
        run: ./gradlew generateCrudDiagram
      - name: Commit updated diagrams
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: "docs: update CRUD diagram [skip ci]"
          file_pattern: "docs/crud-*"

💡 docs/ をコミットする設計について

CRUD図を docs/ フォルダにコミットしておくことで、コードレビュー時に PR の差分として CRUD の変化を確認できます。「このPRでどのテーブルへのアクセスが追加・変更されたか」が一目でわかります。

次のステップ

MyBatis XML対応
Mapper XMLファイルのSQLも同じパイプラインで処理するパーサーを追加する。namespace属性でクラス名を特定できる。
Spring JPA対応
@Query アノテーションの value 属性にある JPQL/SQL を JavaParser で抽出する処理を追加する。
グラフDB連携
行列データを Neo4j や Amazon Neptune に投入し、「このテーブルを削除するクラスの呼び出しグラフ」などをCypher/Gremlinでクエリする。
差分検出
前回実行時のCRUD行列を保存しておき、今回との差分(新規アクセス・削除されたアクセス)をレポートする。

シリーズ完走おめでとうございます

PART 01 から 08 まで読んでいただきありがとうございます。このシリーズで実装したツールは、フレームワークに縛られず、実行環境なしで動き、CI/CDに組み込める実用的な静的解析ツールです。ぜひ実際のプロジェクトで試してみてください。