【要約】SQLAlchemyのIntegrityErrorを一意制約違反の例外としてexceptしてはいけない [Zenn_Python] | Summary by TechDistill
> Source: Zenn_Python
Execute Primary Source
// Problem
開発者がSQLAlchemyのIntegrityErrorを捕捉し、一律に一意制約違反として扱うことで、誤ったエラー情報をユーザーに返してしまう問題がある。不適切な例外処理は、システムの診断を困難にし、ユーザーに混乱を与える。
- ・IntegrityErrorは一意制約違反専用の例外ではない。
- ・NOT NULL制約や外部キー制約違反も、この例外に含まれる。
- ・一意制約が複数あるテーブルでは、どの値が重複したか特定できない。
- ・エラーメッセージの文字列解析は、ロケール依存のため信頼できない。
// Approach
PostgreSQLとpsycopg 3を利用する環境において、エラーの真因を特定するために、ドライバー固有の属性を活用する手法をとる。これにより、どの制約が違反されたかを厳密に判定する。
- ・
exc.origから、ドライバー固有のUniqueViolationを判定する。 - ・
diag.constraint_nameを確認し、特定の制約名と一致するか照合する。 - ・DB側で
UniqueConstraintに、uq_user_emailのような明示的な名前を付与する。 - ・エラー発生後は、
session.rollback()を呼び出し、セッションを正常な状態に戻す。
// Result
この手法を導入することで、開発者はDBの制約に基づいた正確なアプリケーション例外を生成できる。これにより、エラーハンドリングの精度が向上する。
- ・誤ったHTTP 409レスポンスの返却を防止できる。
- ・想定外の整合性制約違反を握りつぶさず、適切に再送出できる。
- ・事前チェック(SELECT)に頼らず、DB制約を正とした堅牢な整合性保証を実現できる。
Senior Engineer Insight
> 実戦において、例外処理の「握りつぶし」は致命的なバグを招く。IntegrityErrorを広範にキャッチすることは、NOT NULL違反などの別問題を隠蔽するリスクがある。制約名に明示的な名前を付ける運用は、コードの可読性と保守性を高める。DBドライバーへの依存は避けられないが、ビジネスロジックの正確性を担保するためには、この程度の抽象化コストは許容すべきである。また、事前チェックとDB制約の併用は、UXと整合性の両立において不可欠な設計である。