プロジェクト

全般

プロフィール

タスク #1439

完了

Entityの項目に空を入れると更新時にエラーが発生する

渡邉 拓英 さんが1年以上前に追加. 1年以上前に更新.

ステータス:
終了
優先度:
急いで
担当者:
開始日:
期日:
進捗率:

100%

予定工数:
実開始日:
DD名:
INCLUDE:
DSN:
バグ区分:
QA分析:
方針(第一貨物):
実終了日:
ツールのバージョン:
AsIsSource行:
進捗計画:
設計・開発者:
画面ID:
機能区分:
機能ID:
レビュー指摘区分:
検査完了日:
検査依頼日:

説明

共通処理で空を初期値に置き換えるように補完する。

1、可能であれば
セッターの共通処理で。

2、ツール出力でセッターを生成。

3、更新時のタイミング(これはやめたい)

結論 独自セッターをツールで出力する。
 ・項目毎に初期値が異なるが正しく設定できる。
 ・速度も一番マシ
 ・ツールがあるからコーディングの物量も何とかなる!

AOP
×→遅くなるのが心配。
  暗黙的過ぎて気づきにくい
  副作用に注意

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

ご質問の意図「セットした直後から値を補完してほしい(例:空文字 → 全角スペース)」という要件をふまえて、AOP方式とDTO層の補完方式を比較し、パフォーマンス面や実装の現実性も含めて説明します。


✅ 要件まとめ(あなたのケース)

  • Oracle の NCHAR に空文字を入れると全角スペースに変換する必要がある。
  • DTOやEntityに値をセットした「直後」に補完したい。
  • 多数のフィールドに共通処理を適用したい。
  • 処理速度に悪影響がない方法が望ましい。

🔷 方法1:AOP(Aspect Oriented Programming)

✨ メリット

  • すべてのセッター呼び出しに横断的に共通処理を追加可能
  • クラスに修正を加えず適用できる(メンテナンス性○)

❌ デメリット

  • リフレクションやプロキシを多用 → 高速性はやや劣る
  • セッター直後に確実に値を補完できるが、開発者が副作用に気づきにくい

📘 実装例(Spring AOP + AspectJ)

@Aspect
@Component
public class SetterInterceptor {

    @Around("execution(* com.example.dto..set*(..))")
    public Object aroundSetter(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        if (args.length == 1 && args[0] instanceof String) {
            String arg = (String) args[0];
            args[0] = (arg != null && arg.trim().isEmpty()) ? " " : arg; // 全角スペース
        }
        return joinPoint.proceed(args);
    }
}

🔷 方法2:DTO/Entity層での補完処理(セッターまたは @Builder 補正)

✨ メリット

  • 処理速度最速(純粋なJavaコード)
  • セッターごとの記述なので意図が明確、バグ発生しにくい

❌ デメリット

  • フィールドが多いと記述が煩雑
  • 共通処理を Utils 等で吸収するのが現実的

📘 実装例(Lombok併用 + 明示的セッター)

@Data
public class UserDto {
    private String name;

    public void setName(String name) {
        this.name = StringNormalizer.normalize(name);
    }
}

public class StringNormalizer {
    public static String normalize(String input) {
        return (input != null && input.trim().isEmpty()) ? " " : input;
    }
}

🔷 方法3:BeanPostProcessor で補完(Bean登録後に実行)

  • DI後の初期化処理(Spring Bean に限定)
  • EntityやDTOでは不向き

🔍 処理速度比較(イメージ)

方法 補完タイミング 処理速度 特徴
AOP セッター呼び出し時 遅い(リフレクション) 横断的、柔軟、遅延初期化
明示的セッター補完 セッター内 最速 明示的で安全、冗長になりがち
Builder補正 DTO生成時 高速 DTO一括初期化に向く

✅ 推奨パターン(あなたの要件に最適)

✨「明示的セッター + 共通ユーティリティ関数」方式

  • 高速(最小オーバーヘッド)
  • セット直後に補完できる
  • テストやバグトレースも容易

📝 おまけ:多数の文字列フィールドに適用するなら

public class NormalizingSetter {

    public static String normalize(String input) {
        return (input != null && input.trim().isEmpty()) ? " " : input;
    }
}

そして各セッターで:

public void setAddress(String address) {
    this.address = NormalizingSetter.normalize(address);
}

✉️ 結論

方法 あなたの目的との相性
AOP 柔軟だがやや重い・副作用に注意
セッター補完 ◎ 最速&シンプルで安全
DTO一括補正 特定処理時に使えるが「直後補完」には不向き

他に「大量の DTO に共通補正を楽に埋め込みたい」や「Spring Validator で対応したい」などの方針があれば、それに合わせた方法も提案できます!

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

Spring + Lombok の @Data を使っていると、セッターは自動生成されるため、共通処理(例えば「空文字をスペースに変換」など)をセッターで実装したい場合は、個別にセッターをオーバーライドする必要があります。


✅ 目的:@Data 使用時に、NCHAR列用セッターで空文字をスペースに変換する共通処理を入れたい


📌 方法1:対象フィールドだけセッターを明示的に書く(Lombokとの併用OK)

import lombok.Data;

@Data
public class YourEntity {

    private Long id;

    private String yourColumn;

    public void setYourColumn(String yourColumn) {
        if (yourColumn != null && yourColumn.trim().isEmpty()) {
            this.yourColumn = " ";
        } else {
            this.yourColumn = yourColumn;
        }
    }
}
  • @Data は他のゲッター・セッターを自動生成しますが、明示的に定義したセッターは上書きされません。
  • このようにして、該当するフィールドにだけ共通処理を埋め込めます。

📌 方法2:共通のユーティリティで処理し、各セッターで使う

public class TextUtils {
    public static String normalizeEmpty(String value) {
        return (value != null && value.trim().isEmpty()) ? " " : value;
    }
}
public void setYourColumn(String yourColumn) {
    this.yourColumn = TextUtils.normalizeEmpty(yourColumn);
}

📌 方法3(高度):全フィールドに共通処理したい → セッターの自動生成は避け、明示的に実装

  • @Data を使わず、@Getter / @Setter を必要なものだけに使うか、完全に自分で記述します。
  • あるいは、AOP や @ModelAttribute・@ControllerAdvice を活用してバリュー変換の層を設ける方法もありますが、これは設計方針によります。

🔁 まとめ

方法 説明 備考
セッターを手書きで上書き @Dataと併用可 最も実用的
ユーティリティ関数化 複数フィールドでも再利用可 セッター内で呼び出し
全面的に自前実装 高度な共通処理に対応 Lombokを部分的に制限

もし対象フィールドが多数ある、あるいはドメイン層で一元管理したい場合は、AOPやDTO層での前処理を提案できます。それも含めて方向性を絞りたい場合はお気軽にお知らせください。

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

import lombok.Data;

@Data
public class YourEntity {

    private Long id;

    private String yourColumn;

    public void setYourColumn(String yourColumn) {
        if (yourColumn != null && yourColumn.trim().isEmpty()) {
            this.yourColumn = " ";
        } else {
            this.yourColumn = yourColumn;
        }
    }
}

関連するチケット 1 (0件未完了 — 1件完了)

関連している バグ #1453: 着電話番号を消して登録するとアベンド終了岡崎 誠

操作

他の形式にエクスポート: Atom PDF