[SpringBoot&JPA]ドメイン分析設計


[1]需要分析


👩🏻‍💻 要求

  • 会員機能(登録/照会)
  • 商品機能(登録/修正/照会)
  • オーダー長(照会/キャンセルオーダー/履歴)
  • その他(商品需要在庫管理/種類:図書、レコード、映画/カテゴリ)
  • [2]ドメインモデルとテーブルの設計



    会員は多様な商品を注文することができ、一度に注文すると多様な商品を選択することができる.→ N:M
    (多対多関係はリレーショナル・データベースだけでなく、エンティティでもあまり使用されません.したがって、上図に示すように、エンティティ(受注商品)を追加することで多対多関係を解決します.)
    継承構造

    エンティティ分析



    カテゴリと商品の多対多

    表解析


    (CATEGORY ITEMは中間表)
    アルバム、図書、映画のジャンルを一つのテーブルにまとめる.次いで、DTYPE列を用いてタイプを区別する.

    📌 実際のコードでは、DBで小文字+スタイルを使用


    (これは、既存の例では会社によって異なります.)

    関連関係マッピング解析


    会員と注文


    :一対多、多対一の関係なので、関連関係が必要な主人は、外来鍵のある注文を関連関係の主人とするのが望ましい.
    (したがって、Order.memberORDERS.MEMBER_ID外部キーにマッピングする)

    商品と注文を注文する


    :多対一の双方向関係.外来キーは受注商品にあるので、関連関係のオーナーです.
    (したがって、OrderItem.orderORDER_ITEM.ORDER_ID外部キーにマッピングする)

    商品と商品を注文する


    :多対一の一方向関係.
    (OrderItem.itemORDER_ITEM.ITEM_ID外部キーにマッピング)

    注文と出荷


    :一対一の双方向関係.
    (Order.deliveryORDERS.DELIVERY_ID外部キーにマッピング)

    カテゴリと商品


    :@ManyToManyを使用したマッピング
    しかし、これは単なる例であり、実際の操作では使用できません.

    📌 外部キーが置かれている場所は関連関係の主人です


    関連関係のオーナーは、外部キーが誰が管理しているのかという問題だけで、ビジネスで優位に立っているわけではありません.
    例えば自動車と車輪があり、一対多の関係では常に一対多の外来鍵があるので、車輪を関連関係の持ち主にすればよい.もちろん、自動車を関連関係の所有者とすることはできないが、自動車が所有者となると、自動車が管理しない車輪表の外部キー値を更新し、管理やメンテナンスが困難になり、追加の個別更新照会の性能問題が発生する可能性がある.

    [3]開発エンティティクラス1


    実験をできるだけ簡単に設計するために、@Getterおよび@Setterを開いて実行したが、実際の動作では、@Getterは開いており、@Setterは必要でない限り閉じている.
    理論的には必要な方法のみを提供するのが理想的であるが、実際の作業ではクエリーを必要とするエンティティが多すぎて、@Getterが開き、@Setterが閉じられる.@Getterは、呼び出しによってデータを変更することはありませんが、@Setterにうっかり触れると危険です.

    [4]開発エンティティクラス2


    📌shift + option + command + L:位置合わせ


    ✔️ Address.Javaでは、値タイプは変更不可に設計されています.@Setterは開かれず、ジェネレータですべての値を初期化し、変更不可能なクラスにします.JPA仕様のエンティティまたはimbeddyタイプ(@Embedded)はjavaデフォルトジェネレータをpublicまたはprotectedに設定する必要があります.
    公共の安全よりも保護するように設定します.
    (JPAにこのような制限があるのは、JPAインプリメンテーションライブラリがオブジェクトの作成時にレプリケーションなどの技術を使用することをサポートしなければならないためです.)

    [5]エンティティを設計する際の注意事項


    1.エンティティはなるべくSetterを使用しない


    (例ではsetterを開いて操作を簡略化します)
    Setterがすべて開いている場合は、変更点が多すぎてメンテナンスが困難です.
    後で再構築でSetterを削除

    2.すべての関連関係を遅延ロードに設定


    インスタントロード(EAGER):ロード時に関連するすべてのコンテンツをロードします.
    インスタント・ロードは予測しにくく、どのSQLが実行されるかを追跡するのは難しい.特にJPQLを実行するとN+1の問題がしばしば発生する.
    したがって、実際の作業では、すべての関連関係を遅延ロード(LAZY)に設定する必要があります.
    関連するエンティティがデータベースで一緒にクエリーする必要がある場合は、fetch joinまたはエンティティグラフィック機能を使用します.(この機能は最適化可能)
    @XToOne(OneToOne,ManyToOne)関係は基本的にインスタントロードなので、直接すべて検索して遅延ロードに設定する必要があります.
    📌 shift + command + F:検索

    fetch joinまたはソリッドグラフィックス機能の使用(必要に応じて)


    3.集合をフィールドで初期化する


    フィールド内の直接初期化コレクション(null問題)は安全です.
    エンティティを永続化すると、仮想名は仮想名に指定された組み込み名に変更されます.getOrders()のように、任意の方法で不正なセットを作成すると、仮想マシンの内部メカニズムに問題が発生する可能性があります.
    したがって,フィールドレベルでの生成が最も安全であり,コードも簡潔になる.

    4.テーブル、カラム名生成ポリシー


    スプリングブートでHypernetのデフォルトマッピングポリシーが変更されたため、実際のテーブルフィールド名は異なります.
  • [参照リンク](https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/htmlsingle/#howto- configure-hibernate-naming-thrategy)
  • [参照リンク](http://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/ Hibernate User Guide.html#命名)
  • 既存のhybernateインプリメンテーション:エンティティのフィールド名をテーブルのカラム名として使用
    スプリング起動新規設定(エンティティ(フィールド)→テーブル(列)
    1.キャラメルボックス→アンダーコード(memberPoint→memberpoint)
    2. . → ``
    3.大文字→小文字

    5. cascade = CascadeType.ALL



    6.関連メソッド

    // Order.java
        //==연관관계 메소드==//
        public void setMember(Member member) {
            this.member = member;
            member.getOrders().add(this);
        }
    
        public void addOrderItem(OrderItem orderItem) {
            orderItems.add(orderItem);
            orderItem.setOrder(this);
        }
    
        public void setDelivery(Delivery delivery) {
            this.delivery = delivery;
            delivery.setOrder(this);
        }
    
    // Category.java
        //==연관관계 메소드==//
        public void addChildCategory(Category child) {
            this.child.add(child);
            child.setParent(this);
        }