SpringBoot]ショッピングモールプロジェクト(7)-関連マッピング


▼▼関連関係マッピングタイプ
マッピング関係は4つあります.
  • 一対一(1:1):@OneToOne
  • 対多(1:N):@OneToMany
  • マルチペア(N:1):@ManyToOne
  • マルチペアマルチ(N:M):@ManyToMany
  • 例えば、デパートでは会員一人一人が自分のショッピングバスケットを持っています.
    カートの観点から、自分でマッピングしたメンバー=>1対1のマッピングを持つことになります.
    1つのショッピングバスケットに複数の商品を含めることができます=>1対のマルチマッピング
    ▼▼1対1の一方向マッピング
    カートエンティティを作成し、メンバーエンティティとの関連マッピングを設定します.
    カートソリッド設計
    @Entity
    @Table(name = "cart")
    @Getter @Setter
    @ToString
    public class Cart {
    
        @Id
        @Column(name = "cart_id")
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @OneToOne
        @JoinColumn(name = "member_id")
        private Member member;
    }
    カートエンティティは、メンバーエンティティの1対1の一方向マッピング形式を一方的に参照します.
    cartテーブルはmember id列を外部キーとします.
    CartRepositoryインタフェースを作成したら、CartTestを作成しましょう.
    @SpringBootTest
    @Transactional
    @TestPropertySource(locations="classpath:application-test.properties")
    class CartTest {
    
        @Autowired
        CartRepository cartRepository;
    
        @Autowired
        MemberRepository memberRepository;
    
        @Autowired
        PasswordEncoder passwordEncoder;
    
        @PersistenceContext
        EntityManager em;
    
        public Member createMember(){
            MemberFormDto memberFormDto = new MemberFormDto();
            memberFormDto.setEmail("[email protected]");
            memberFormDto.setName("홍길동");
            memberFormDto.setAddress("서울시 마포구 합정동");
            memberFormDto.setPassword("1234");
            return Member.createMember(memberFormDto, passwordEncoder);
        }
    
        @Test
        @DisplayName("장바구니 회원 엔티티 매핑 조회 테스트")
        public void findCartAndMemberTest(){
            Member member = createMember();
            memberRepository.save(member);
            Cart cart = new Cart();
            cart.setMember(member);
            cartRepository.save(cart);
    
            em.flush();
            em.clear();
    
            Cart savedCart = cartRepository.findById(cart.getId())
                    .orElseThrow(EntityNotFoundException::new);
            assertEquals(savedCart.getMember().getId(), member.getId());
        }
    
    }
    JPAは、データを永続コンテキストに格納し、トランザクションの終了時にflush()を呼び出してデータベースに反映します.
    永続性コンテキストからエンティティを問合せた後、永続性コンテキストにエンティティがない場合、JPAはデータベースを問合せます.実際のデータベースからカートエンティティをインポートすると、永続コンテキストが空になり、メンバーエンティティもインポートされるかどうかを確認します.
    エンティティを問い合せるときに、エンティティとマッピングされたエンティティを一度に問い合せることをインスタント・ロードと呼びます.1対1または複数対1にマッピングされている場合は、「≪即時ロード|Load Now|Essbase_Studio≫」をデフォルトのFetchポリシーに設定します.
    ▼▼多対一の一方向マッピング
    ショッピングバスケットにはいろいろな商品が入れられます.同じ商品を複数注文することもできます.
    ショッピングカートプロジェクトの図面を設計する
    CartItem
    @Entity
    @Getter @Setter
    @Table(name="cart_item")
    public class CartItem {
        
        @Id
        @GeneratedValue
        @Column(name = "cart_item_id")
        private Long id;
        
        @ManyToOne
        @JoinColumn(name="cart_id")
        private Cart cart;
        
        @ManyToOne
        @JoinColumn(name = "item_id")
        private Item item;
        
        private int count;
    }
    
    1つのショッピングバスケットには複数の商品が含まれ、1つの商品は複数のショッピングバスケットのショッピングバスケット商品として使用できるため、@ManyToOneオペレーティングシステムを使用して多対一関係にマッピングされます.
    ▼▼▼多対一/多対多双方向マッピング
    双方向マッピングとは、2つの一方向マッピングを指します.
    受注と受注商品マッピングによって双方向マッピングを理解しましょう.
    まず、受注エンティティを設計します.
    受注ドメインエンティティの設計
    OrderStatus
    @Entity
    @Table(name = "orders")
    @Getter @Setter
    public class Order {
    
        @Id @GeneratedValue
        @Column(name = "order_id")
        private Long id;
    
        @ManyToOne
        @JoinColumn(name = "member_id")
        private Member member;
    
        private LocalDateTime orderDate; //주문일
    
        @Enumerated(EnumType.STRING)
        private OrderStatus orderStatus; //주문상태
    
        private LocalDateTime regTime;
        private LocalDateTime updateTime;
        
    }
    1つのメンバーは複数回注文できるため、複数対1の一方向マッピングです.
    設計OrderItem.
    @Entity
    @Getter @Setter
    public class OrderItem {
        
        @Id @GeneratedValue
        @Column(name = "order_item_id")
        private Long id;
        
        @ManyToOne
        @JoinColumn(name = "item_id")
        private Order order;
        
        private int orderPrice; //주문 가격
        
        private int count; //수량
        
        private LocalDateTime regTime;
        
        private LocalDateTime updateTime;
    }
    1つの商品が複数の注文商品であり、1つの注文が複数の商品を注文できるため、複数の一方向マッピングを設定します.
    エンティティが双方向に関連付けられている場合、オブジェクトの参照は2つであり、外部キーは1つであるため、誰が外部キーを管理するかを指定する必要があります.
  • 関連関係の所有者が外部鍵を有する場所
  • に設定.
  • 関連関係の所有者管理(登録、修正、削除)
  • 所有者は、関連関係のマッピング時にmappedBy属性の値を関連関係の所有者
  • に設定.
  • 非主人方読取り専用
  • OrderItemと関連関係マッピングをOrderエンティティに追加します.
    @Entity
    @Table(name = "orders")
    @Getter @Setter
    public class Order {
    
        @Id @GeneratedValue
        @Column(name = "order_id")
        private Long id;
    
        @ManyToOne
        @JoinColumn(name = "member_id")
        private Member member;
    
        private LocalDateTime orderDate; //주문일
    
        @Enumerated(EnumType.STRING)
        private OrderStatus orderStatus; //주문상태
        
        @OneToMany(mappedBy = "order")
        private List<OrderItem> orderItems = new ArrayList<>();
    
        private LocalDateTime regTime;
        private LocalDateTime updateTime;
    
    }
    受注商品エンティティと一対のマルチマッピングを行います.外部キー(order id)はorder itemテーブルにあるため、関連関係の所有者はOrderItemエンティティです.Orderエンティティは所有者ではないため、「mappedBy」プロパティを使用して関連関係の所有者を設定できます.
    次は永続星戦で、遅延ロードについて勉強し続けます.