30.値タイプ(1)


30.値タイプ(1)


JPAのデータ型を最大に分類すると、エンティティ型と値型に分けられます.エンティティタイプは@Entityとして定義されたオブジェクトで、値タイプはint、Integer、Stringのように単純に値として使用されるJava基本タイプまたはオブジェクトを指します.エンティティ・タイプは識別子で追跡できますが、値タイプには識別子がなく、数値や文字などの属性のみが追跡できません.例えば、いわゆる会員実体は、その会員の身長や年齢値を変更しても同じ会員である.識別子を保持する限り、メンバーのすべてのデータを変更することもできます.逆に、数値100を200に変更すると、まったく異なる値に置き換えられます.たとえば,メタタイプは生きている生物であり,値タイプは単純な数値情報である.
値のタイプは、次の3つに分けられます.
  • デフォルトタイプ(basic value type)
    -Javaのデフォルトタイプ(int、doubleなど)
    -Rapperクラス(Integerなど)
    - String
  • 埋め込みタイプ(複合値タイプ)
  • 集約値タイプ(集合値タイプ)
  • デフォルトタイプは、String、intなどのJavaが提供する基本データ型で、imbeddyタイプはJPAでユーザー定義された値タイプです.最後に、コレクション値タイプは、1つ以上の値タイプを格納するために使用されます.デフォルトのタイプから順に説明しましょう.

    1.デフォルトのタイプ


    最も簡単なデフォルトタイプについて説明します.
    @Entity
    public class Member {
    
        @Id @GeneratedValue
        private Long id;
        private String name;
        private int age;
        ...
    }
    上記の例のメンバーでは、String、intは値タイプです.メンバー・エンティティにはidの識別子値とライフサイクルがありますが、値タイプname、age属性には識別子値がなく、ライフサイクルもメンバー・エンティティに依存します.したがって、メンバーエンティティインスタンスを削除すると、name、age値も削除されます.また、価格タイプは共有できません.たとえば、他のメンバーエンティティの名前を変更すると、私の名前も変更されるとは考えられません.
    当たり前のような内容を説明していると、少し慌ててしまいます.次に、javaが提供するデフォルト値タイプではなく、直接値タイプを定義します.
    Javaではintやdoubleのような基本タイプ(primitive type)は絶対に共有されません.例えば、a=bコードはbの値をコピーし、aを入力する.もちろん、RapperクラスやStringクラスのようなIntegerのような特殊なクラスもあります.これらはオブジェクトですが、Java言語ではデフォルトタイプとして使用することがサポートされているため、デフォルトタイプとして定義されます.

    2.埋め込みタイプ(複合タイプ)


    新しい値タイプを直接定義して使用することができ、JPAはそれを埋め込みタイプ(embedded type)と呼ぶ.重要なのは,直接定義したimbeddyタイプもint,Stringのように値タイプである.例を使用してimbeddyタイプを詳細に説明します.
    @Entity
    public class Member {
    
        @Id @GeneratedValue
        private Long id;
        private String name;
        
        // 근무 기간
        @Temporal(TemporalType.DATE) java.util.Date startDate;
        @Temporal(TemporalType.DATE) java.util.Date endDate;
        
        // 집 주소 표현
        private String city;
        private String street;
        private String zipcode;
        // ...
    }
    上記の例は、通常のメンバーエンティティです.誰かにこの実体を説明したいなら、私はそう言います.
  • 会員エンティティは、氏名、開始平日、終了平日、住所都市、住所番号、住所郵便番号を有する.
  • この解釈は単純に情報を解放しただけだ.また、勤務開始日と郵便番号の間には何の関連もありません.これよりも、以下のように解釈した方が明確です.
  • 会員エンティティには、名前、勤務時間、およびホームアドレスがあります.
  • 会員が詳細なデータを保持するのは対象に向いていないので、凝集力を低下させるだけです.逆に、勤務時間や住所などのタイプがあれば、コードがより明確になります.imbeddyタイプを使用して[勤務時間、住所]を持つ.
  • 値タイプ適用メンバーエンティティ
  • @Entity
    public class Member {
    
        @Id @GeneratedValue
        private Long id;
        private String name;
        
        @Embedded Period workPeriod;     // 근무 기간
        @Embedded Address homeAddress;   // 집 주소
        // ...
    }
  • 期間埋め込み
  • @Embeddable
    public class Period {
    
        @Temporal(TemporalType.DATE) java.util.Date startDate;
        @Temporal(TemporalType.DATE) java.util.Date endDate;
        // ..
        
        public boolean isWork(Date date) {
            // .. 값 타입을 위한 메소드를 정의할 수 있다.
        }
    }
  • アドレスimbeddyタイプ
  • @Embeddable 
    public class Address {
    
        @Column(name = "city")    // 매핑할 컬럼 정의 가능
        private String city;
        private String street;
        private String zipcode;
        // ..
    }

    上記の例(値タイプを適用したメンバーエンティティ)から、メンバーエンティティがより意味があり、凝集力があることがわかります.
  • の上の例では、startDate、endDateはPeriodクラスにマージされる.
  • の上記の例(アドレスimbeddyタイプ)は、city、street、zipcodeをAddressクラスにマージする.
  • 新しく定義した値タイプは繰り返し使用でき、凝集度も高い.また、上記の例(期限切れタイプ)のPeriodについても説明します.また、isWork()などの値タイプのみを使用する有意義なメソッドを作成することもできます.
    imbeddyタイプを使用するには、次の2つの方法が必要です.ちなみに、両者の1つは省略できます.
  • @Embeddable:値タイプを定義すると
  • と表示されます.
  • @Embedded:
  • を使用値タイプで表示
    また、imbeddyタイプの基本ジェネレータが必要です.
    すべての値タイプ(imbeddyタイプを含む)は、エンティティのライフサイクルに依存するため、エンティティとimbeddyタイプの関係をUMLで表すと、複合関係(上図)になります.
    ハイバーネットはimbeddyタイプを素子(component)と呼ぶ.

    1.埋め込みタイプとテーブルマッピング


    imbeddyタイプをデータベース・テーブルにマッピングする方法を次の図に示します.

    imbeddyタイプはエンティティの値にすぎません.したがって、値は、属するエンティティのテーブルにマッピングされます.例では、imbeddyタイプを使用する前後にマッピングされるテーブルは同じです.
    imbeddyタイプは、オブジェクトとテーブルのマッピングを非常に細かくします.設計されたORMアプリケーションのクラス数は、マッピングされたテーブル数よりも多くなります.
    ORMを使用して開発しない場合、テーブルバーとオブジェクトフィールドの多くは1:1にマッピングされます.アドレスや勤務時間等値タイプのクラスを作成し、よりオブジェクト向けに開発し、SQLを直接使用する場合は、1つのクラスを1つのテーブルにマッピングするのも難しい作業ですが、1つのテーブルに複数の閉パケットをマッピングすることは考えられません.これらの冗長な繰り返し作業はJPAに任せ,より細かくオブジェクト向けモデルの設計に集中する.
    組み込みおよびUML
    UMLでは、imbeddy値タイプを下図のように簡単に表すことができます.

    2.imbeddyタイプに関連


    埋め込みタイプには、値タイプを含めるか、エンティティを参照できます.JPA規格を使用して、imbeddyタイプの関連関係を理解するために提供される次のコードおよび図の例を説明します.
    エンティティが共有できることを示すので参照します.値タイプは特定のマスターに属し、論理概念では共有されないため含まれます.
    @Entity
    public class Member {
    
        @Embedded Address address;           // 임베디드 타입 포함
        @Embedded PhoneNumber phoneNumber;   // 임베디드 타입 포함
        // ...
    }
    
    @Embeddable
    public class Address {
        String street;
        String city;
        String state;
        @Embedded Zipcode zipcode;           // 임베디드 타입 포함
    }
    
    @Embeddable
    public class ZipCode {
        String zip;
        String plusFour;
    }
    
    @Embeddable
    public class PhoneNumber {
        String areaCode;
        String localNumber;
        @ManyToOne PhoneServiceProvider provider;    // 엔티티 참조
        ...
    }
    
    @Entity
    public class PhoneServiceProvider {
        @Id String name;
        ...
    }
    上記の例では、値タイプAddressには値タイプのZIPコードが含まれています.値タイプPhoneNumberはエンティティタイプPhoneServiceProviderです.

    3.@AttributeOverride:属性の再定義


    埋め込みタイプで定義されたマッピング情報を再定義するには、@AttributeOverrideをエンティティで使用します.例えば、会員に住所が必要な場合は、どうすればいいですか?
    @Entity
    public class Member {
    
        @Id @GeneratedValue
        private Long id;
        private String name;
        
        @Embedded Address homeAddress;
        @Embedded Address companyAddress;
    }
    上記の例では、メンバーエンティティは、ファミリーアドレスに会社アドレスを追加します.問題は、テーブルにマッピングされたカラム名が重複していることです.この場合、以下の例に示すように、@AttributeOverridesを使用してマッピング情報を再定義する必要があります.
    @Entity
    public class Member {
    
        @Id @GeneratedValue
        private Long id;
        private String name;
        
        @Embedded Address homeAddress;
        
        @Embedded
        @AttributeOverrides({
            @AttributeOverride(name="city", column=@Column(name
                = "COMPANY_CITY")},
            @AttributeOverride(name="street", column=@Column(name
                = "COMPANY_STREET")},
            @AttributeOverrdie(name="zipcode", column=@Column(name
                = "COMPANY_ZIPCODE")}
        })
        Address companyAddress;
    }    
    次の例で作成したテーブルは再定義に変更されました.
    CREATE TABLE MEMBER (
        COMPANY_CITY varchar(255),
        COMPANY_STREET varchar(255),
        COMPANY_ZIPCODE varchar(255),
        city varchar(255),
        street varchar(255),
        zipcode varchar(255),
        ...
    )
    @AttributeOverrideを使用すると、アシスタントが多すぎるため、エンティティコードが乱雑になります.幸いなことに、1つのエンティティに同じ埋め込みタイプを繰り返し使用することは多くありません.
    @AttributeOverdiesはエンティティで設定する必要があります.imbeddyタイプにimbeddyタイプがある場合でも、エンティティに設定する必要があります.

    4.埋め込みタイプとnull


    imbeddyタイプがnullの場合、マッピングされたcolumn値はnullです.
    member.setAddress(null);    // null 입력
    em.persist(member);
    メンバー・テーブル・アドレスに関連するCITY、STREET、ZIPCODEのカラム値はすべてNULLです.
    リファレンス
  • Java ORM標準JPAプログラミング