節約プログラマー雑記

ER図からDBの自動生成

DB構築の作業簡略化を目的として、draw.ioで作成したER図をデータベースの設計図(青写真)として利用し、アプリケーションのコード(ORM)を介して実際のデータベース(PostgreSQL)を構築する仕組みを採用しました。

具体的な生成プロセスは以下の3つのステップで構成されており、ER図の設計は人の領域としつつも、2, 3の工程をGoogle Antigravity(AI)を利用することで自動化を試みました。

1. データモデリング(draw.io)

まず、draw.ioを使用して視覚的にデータベースの構造を定義します。ここでは、各テーブルの役割、必要なカラム(項目)、テーブル間のリレーションシップ(1対多、多対多などの関係性)を設計します。これがデータベース構築の「設計図」となります。

ER図
図1: draw.ioで作成したER図(er.drawio.svg)

2. ORMモデルへの変換(Python / SQLAlchemy)

設計されたER図をもとに、Google Antigravityを利用して、図を読み込ませ、Pythonのコードへ落とし込みます。本プロジェクトでは「SQLAlchemy」というORM(Object-Relational Mapper)ライブラリを使用しています。
models ディレクトリ内(user.pyaccount.pyuser_account.pyなど)に、ER図の各テーブルに対応するPythonの「クラス」を作成し、カラムやリレーションをプログラムの変数として定義します。

  • 利点: SQL(データベース専用言語)を直接書く必要がなくなり、Pythonのコードとしてテーブル定義やデータ操作をバージョン管理(Gitなど)できるようになります。
  • 注意点: さきほどのER図の時点ではカラムの属性が指定できていないため、Pythonのコードでカラムのデータ型、桁数を指定します。

実装例:

user.py (ユーザーマスタ)
from datetime import datetime
from . import db

class UserMaster(db.Model):
    __tablename__ = 'user_master'

    user_id = db.Column(db.String(50), primary_key=True)
    password = db.Column(db.String(256))
    privilege = db.Column(db.String(50))
    first_name = db.Column(db.String(100))
    last_name = db.Column(db.String(100))
    update_date_time = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    # アカウントとの関連 (中間テーブル経由)
    accounts = db.relationship('UserAccounts', back_populates='user', cascade='all, delete-orphan')

    def __repr__(self):
        return f'<UserMaster {self.user_id}: {self.first_name} {self.last_name}>'
account.py (アカウントマスタ)
from datetime import datetime
from . import db

class AccountMaster(db.Model):
    __tablename__ = 'account_master'

    account_id = db.Column(db.String(50), primary_key=True)
    account_name = db.Column(db.String(256))
    update_date_time = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    # ユーザーとの関連 (中間テーブル経由)
    users = db.relationship('UserAccounts', back_populates='account', cascade='all, delete-orphan')

    def __repr__(self):
        return f'<AccountMaster {self.account_id}: {self.account_name}>'
user_account.py (ユーザーアカウント中間テーブル)
from datetime import datetime
from . import db

class UserAccounts(db.Model):
    __tablename__ = 'user_accounts'

    user_id = db.Column(db.String(50), db.ForeignKey('user_master.user_id'), primary_key=True)
    account_id = db.Column(db.String(50), db.ForeignKey('account_master.account_id'), primary_key=True)
    register_date_time = db.Column(db.DateTime, default=datetime.utcnow)

    # リレーション設定
    user = db.relationship('UserMaster', back_populates='accounts')
    account = db.relationship('AccountMaster', back_populates='users')

    def __repr__(self):
        return f'<UserAccounts User:{self.user_id} Account:{self.account_id}>'

3. データベースへの反映(マイグレーション / テーブル生成)

作成したPythonのモデル定義をもとに、実際のPostgreSQLデータベースにテーブルを構築します。
FlaskアプリケーションとSQLAlchemyの連携機能(db.create_all() や、Flask-Migrateなどのマイグレーションツール)を実行することで、Pythonのクラス定義が自動的に CREATE TABLE などのSQLコマンドに翻訳され、データベース上に物理的なテーブルが生成されます。


【補足:直接SQLを生成するアプローチについて】

draw.ioのプラグイン機能を利用して、図から直接SQL(DDL)のコードを出力し、それをデータベースに流し込むことも可能です。しかし、今回は保守性やアプリケーションとの連携を重視し、「ER図での可視化」→「Pythonモデルでのコード化」→「ORMによるDB生成」というワークフローを基本としています。