[JPA]9枚価格タイプ


この記事は、キム・ヨンハンの『Java ORM標準JPAプログラミング』を読んで学習内容を整理したものだ.
  • デフォルトタイプ
  • 埋め込み
  • 値タイプおよび不変オブジェクト
  • 値タイプ比較
  • 値タイプセット
  • JPAのデータ型を大きく分類すると、エンティティ型と値型に分けられます.

  • エンティティタイプ
  • @Entity定義のオブジェクト

  • 値のタイプ
  • デフォルト・タイプ
  • Java基本タイプ(int,double,...)
  • Rapperクラス(Integer,...)
  • String
  • 埋め込み
  • コレクション値タイプ
  • 1.デフォルトのタイプ

    @Entity
    public class Member { // 엔티티 타입
    	@Id @GeneratedValue
        private Long id;
        
        private String name; // 값 타입
        private int age; // 값 타입
  • 値タイプname、age属性に識別子値はなく、ライフサイクルもメンバーエンティティに依存します.
  • 値タイプは共有できません.
  • 2.埋め込み式


    新しい値タイプを直接定義して使用します.
    @Entity
    public class Member {
    	@Id @GeneratedValue
        private Long id;
        
        private String name;
        private int age;
        
        @Embedded Period workPeriod; // 임베디드 타입
    }
        
    @Embeddable
    public class Period {
    	@Temporal(TeporalType.DATE) java.util.Date startDate;
      	...
    }
    組み込みテクノロジー
  • @Embeddable:値タイプを定義した場所に表示
  • @Embedded:使用値タイプの場所に表示
    ✔¥2のうち1つは省略できます.
  • 2.1テーブルマッピング



    imbeddyタイプは、エンティティの値であるため、属するエンティティのテーブルにマッピングされます.
    imbeddyタイプを使用する前と後でマッピングされるテーブルは同じです.

    2.2関連


    埋め込みタイプには、値タイプを含めるか、エンティティを参照できます.
  • エンティティを参照-共有可能
  • 値タイプを含む-特定の所有者に属し、論理概念上は共有しない
  • @Entity
    public class Member {
    	
        @Embedded Address address; 		   // 임베디드 타입 포함
        @Embedded PhoneNumber phoneNumber; // 임베디드 타입 포함
    }
        
    @Embeddable
    public class Address {
    
    	String street;
        String city;
    	@Embeddable Zipcode zipcode; // 임베디드 타입 포함
      	...
    }
    
    @Embeddable
    public class Zipcode {
    
    	String zip;
      	...
    }
    
    @Embeddable
    public class PhoneNumber {
    
    	@ManyToOne PhoneServiceProvider provider // 엔티티 참조
      	...
    }
    
    @Entity
    public class PhoneServiceProvider {
    	
        @Id String name;
        ...
    }
    

    2.3属性の再定義

    @AttributeOverride:埋め込みタイプで定義されたマッピング情報を再定義します.
    @Entity
    public class Member {
    	@Id @GeneratedValue
        private Long id;
        private String name;
        
        @Embedded Address homeAddress;
        @Embedded Address companyAddress; // 주소 추가
    }
    テーブルにマッピングされたカラム名が重複します.@AttributeOverrideマッピング情報を再定義します.
    @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")),
            @AttributeOverride(name="zipcode", column=@Column(name = "COMPANY_ZIPCODE"))
        })
        Address companyAddress; // 주소 추가
    }
    @AttributeOverrideエンティティに設定する必要があります.
    埋め込みタイプに埋め込みタイプがある場合でも、エンティティに設定する必要があります.❓

    2.4 null


    imbeddyタイプがnullの場合、マッピングされたcolumn値はnullです.

    3.値タイプと不変オブジェクト


    3.1共有を参照


    imbeddyタイプと同じ値タイプを複数のエンティティで共有することはできません.
    member1.setHomeAddress(new Address("OldCity"));
    Address address = member1.getHomeAddress();
    
    address.setCity("NewCity"); // 회원1의 address 값을 공유해서 사용 -> 회원1의 주소도 변경
    member2.setHomeAddress(address);
    これらの副作用を防止するには、値をコピーして使用する必要があります.

    3.2箱タイプコピー

    member1.setHomeAddress(new Address("OldCity"));
    Address address = member1.getHomeAddress();
    
    // 회원1의 address 값을 복사해서 새로운 newAddress 값을 생성
    Address newAddress = address.clone();
    
    newAddress.setCity("NewCity");
    member2.setHomeAddress(newAddress);
    imbeddyタイプはjavaの基本タイプではなく、オブジェクトタイプです.
    デフォルトのタイプ-値をコピーして渡す
    オブジェクトタイプ-参照値を渡す
    
    Address a = new Address("OldCity")
    
    Address b = a.clone(); // 항상 복사해서 넘겨야 한다.
    // Address b = a // 이렇게 참조만 넘기면 공유 참조의 부작용이 발생한다.
    
    b.setCity("NewCity");
    オブジェクトを挿入するたびにインスタンスをコピーして挿入することで、共有参照を回避できます.
    ただし、元の参照値をコピーせずに直接渡すのは止められません.
    オブジェクトの共有参照は避けられません.
    オブジェクトの値の変更を防止します.
    ex)setterのような修正者を削除する方法.

    3.3不変オブジェクト


    ソースから副作用を防止するために、値タイプはできるだけ不変のオブジェクトとして設計する必要があります.
    不変オブジェクトの値はクエリー,変更
    不変のオブジェクトも最終的にはオブジェクトです.
    *インスタンスの参照値の共有は回避できません.
    インスタンスの値は変更できないため、副作用は発生しません.
    不変オブジェクトを作成!
    モディファイヤを作成せずにジェネレータとして値のみを設定します.
    値を変更する必要がある場合は、新しいオブジェクトを作成して使用する必要があります.

    4.比較値タイプ

    int a = 10;
    int b = 10;
    
    Address a = new Address("가", "나", "다");
    Address b = new Address("가", "나", "다");
  • コンシステンシ比較:インスタンスの参照値を比較し、==使用
  • 同等比較:インスタンスの値を比較し、equals()
  • を使用
    値タイプを比較する場合は、a.equals(b)を使用して同等に比較します.

    5.値タイプの集合


    1つ以上の値タイプを保存するには、コレクションに保存し、@ElementCollection@CollectionTableを使用します.
    @Entity
    public class Member {
    	@Id @GeneratedValue
        private Long id;
        private String name;
        
        @Embedded Address homeAddress;
        
        @ElementCollection
        @CollectionTable(name = "FAVORITE_FOODS", joinColumns = @JoinColumn(name = "MEMBER_ID"))
        @Column(name = "FOOD_NAME")
        private Set<String> favoriteFoods = new HashSet<String>();
        
        @ElementCollection
        @CollectionTable(name = "ADDRESS", joinColumns = @JoinColumn(name = "MEMBER_ID"))
        private List<Address> addressHistory = new ArrayList<Address>();
        
    }
  • @ElementCollection:値タイプセット
  • @CollectionTable:マッピング集合テーブル

  • リレーショナル・データベースのテーブルには、カラムのセットを含めることはできません.そのため、個別のテーブルを追加する必要があります.

    5.1値タイプのセットの使用


    値タイプセットの登録

    Member member = new Member();
    
    // 임베디드 값 타입
    member.setHomeAddress(new Address("ㄱ","ㄴ","ㄷ"));
    
    // 기본 값 타입 컬렉션
    member.getFavoriteFoods().add("r");
    member.getFavoriteFoods().add("s");
    
    // 임베디드 값 타입 컬렉션
    member.getAddressHistory().add(new Address("1"));
    member.getAddressHistory().add(new Address("2"));
    
    em.persist(member);
    値タイプのセットには、孤立オブジェクトを永続的に移行および除去する機能が必要です.

    値タイプセットの変更

    Member member = em.find(Member.class, 1L);
    
    // 임베디드 값 타입
    member.setHomeAddress(new Address("ㄱ","ㄴ","ㄷ"));
    
    // 기본 값 타입 컬렉션
    Set<String> favoriteFoods = member.getFavoriteFoods();
    favoriteFoods.remove(r); // String 타입을 수정할 수 없다.
    favoriteFoods().add("s");
    
    // 임베디드 값 타입 컬렉션
    List<Address> addressHistory = member.getAddressHistory();
    addressHistory.remove(new Address("1")); // 값 타입은 불변하므로 삭제 후 새로 등록한다.
    addressHistory.add(new Address("2"));

    5.2値タイプ集合の制限


    値タイプのセットに保存された値は、別のテーブルに保存されます.これらの値を変更すると、データベース内の元のデータが見つかりにくくなります.
    この問題を解決するために、JPA実施者が値タイプのセットを変更した場合
  • 値タイプのセットがマッピングされたテーブルのすべての関連データを削除
  • 現在の値タイプの集合オブジェクトのすべての値をデータベースに再保存します.
  • したがって、値タイプセットがマッピングされたテーブルに大量のデータがある場合は、値タイプセットではなく新しいエンティティを作成し、1対多の関係に設定します.