ABAP DUMP ERROR 24시

컬렉션 값 타입 (Collection value type)의 한계 본문

[WEB]Back-end/JPA

컬렉션 값 타입 (Collection value type)의 한계

이운형 2022. 1. 20. 18:59
반응형

# 인프런 김영한의 자바 ORM 표준 JPA 프로그래밍 - 기본편을 개인적으로 정리한 글입니다.

 

 

<까먹지 말자> 기본 base


 

정리


Q. Entity Type 과 값Type 비교해줘

Entity type 값 타입
식별자 존재 식별자 없음
생명주기 존재 생명주기를 엔티티에 의존
공유가능 공유하면 큰일 난다.(복사해서 사용해라)

 

Q. 컬렉션이 뭐야?

A. 값 타입을 컬렉션에 담아서 쓰는 것 //  타입 하나하나를 모아주는 역할.  다 PK값을 갖는다.

 

Q.  왜 컬렉션 식별자 하나 하나를 PK로 사용하는거야?

A. 해당 테이블은 값 타입으로 정의되어있다.

하나로 묶어서 식별자로 두는 방법은 엔티티를 사용하는 방법이다.
따라서, 테이블에 값들만 저장하고 사용하기 위해서  pk로 둔다.

 

Q. 컬렉션 어떻게 사용해?

A. @ElementCollection, @CollectionTable 을 사용해!

//    @ElementCollection
//    @CollectionTable(name = "address",
//    joinColumns = @JoinColumn(name = "member_id"))
//    private List<Address> addressHistory = new ArrayList<>();

private List<Address> addressHistory = new ArrayList<>(); 만들기 // 변수 생성

그 위에 @ElementCollection 만들기

@CollectionTable( name = " db에 만들 table 이름", @JoinColumn(db와 조인할 컬럼 이름))

끝.

 

Q. 값 타입 그리고 객체 타입의 한계가 뭐야?

A. 복사 해서 재정의 후 사용하지 않으면 Side Effect가 난다. // 직원 이름을 바꿀려고 change name("홍길동") 했다가 모든 직원이 홍길동으로 변한다.

즉 , 객체 타입은 참조 값을 직접 대입하는 것을 막을 방법이 없다.

 

=> 항상 값을 복사해서 사용해야만 공유 참조로 인한 부작용을 피할수 있다.(side effect를 피할수 있다.)

=> Embedded 타입 처럼 직접 정의한 값타입은 자바의 기본 타입이 아닌 객체 타입이므로 추적이 어려움.

 

Q.그럼 어떻게 값 타입을 사용해야해?

A. 불변 객체로 만들면되.

 

Q.불변 객체가 뭐야? 어떻게 만들어?=> 변경이 불가능한 객체

A.

1. 객체 타입을 수정하지 않도록 만든다. // public 대신 private 로 만들어 사용하자!

2. @Setter를 사용하지 말자// @Setter는 그냥 사용하지 말자.

3. Integer 나 String 같은 자바가 제공하는 불변 객체를 사용하자.

4. DTO, Entity를 따로 만들어 사용한다.

5. Entity로 만들어 사용하자!! // 가장 NICE  그냥 이걸로 만들어!

 

 

살펴보기


Q. 컬렉션이 뭐야?

 

A. 값 타입을 컬렉션에 담아서 쓰는 것 //  타입 하나하나를 모아주는 역할.  다 PK값을 갖는다.

 

 

 

<Embbed 타입, Collection 타입 수정 방법>

            //embedded type 수정하는 방법.
            //Address address = new Address("city", "street", "10000");
//
//            Member member1 = new Member();
//            member1.setUsername("member1");
//            member1.setHomeAddress(address);
//            em.persist(member1);
//
//            Address copyAddress = new Address(address.getCity(), address.getStreet(), address.getZipcode());
//
//            Member member2 = new Member();
//            member2.setUsername("member2");
//            member2.setHomeAddress(copyAddress);
//            em.persist(member2);
//
//            member1.getHomeAddress().setCity("newCity");

Address copyAddress 객체를 새로 생성해서 복사 한다음, 변환해!!

 

Q. 컬렉션 어떻게 사용해?

//    @ElementCollection
//    @CollectionTable(name = "address",
//    joinColumns = @JoinColumn(name = "member_id"))
//    private List<Address> addressHistory = new ArrayList<>();
//    @ElementCollection
//    @CollectionTable(name = "favorite_food",
//            joinColumns = @JoinColumn(name = "member_id"))
//    @Column(name = "food_name")
//    private Set<String> favoriteFoods = new HashSet<>();

다음과 같이 @ElementCollection을 설정한 후에! 객체를 꼭 복사후 재정의 해서 사용한다.

그리고 equal and Hashcode 를 정의하자..

 

<수정, 삭제 >

//            //값 타입 컬렉션 사용 예제
//
//            Member member = new Member();
//            member.setUsername("member1");
//            member.setHomeAddress(new Address("HomeCity", "street", "10000"));
//
//            member.getFavoriteFoods().add("치킨");
//            member.getFavoriteFoods().add("족발");
//            member.getFavoriteFoods().add("피자");
//
//            member.getAddressHistory().add(new Address("old1", "street", "10000"));
//            member.getAddressHistory().add(new Address("old2", "street", "10000"));
//
//            em.persist(member);
//            em.flush();
//            em.clear();

Address  객체를 새로 생성해서 복사 한다음, 변환해!!

 

<조회>

//            // 값 타입 조회
//            Member member = new Member();
//            Member findMember = em.find(Member.class, member.getId());
//
//            List<Address> addressHistory = findMember.getAddressHistory();
//            for (Address address : addressHistory){
//                System.out.println(" addreses= " + address.getCity());
//            }
//
//            Set<String> favoriteFoods = findMember.getFavoriteFoods();
//            for (String favoriteFood: favoriteFoods){
//                System.out.println("favoriteFood = " + favoriteFood);
//            }

 

Q.불변 객체가 뭐야? 어떻게 만들어?

import javax.persistence.*;

@Entity
@Table(name = "address")
public class AddressEntity {

    @Id @GeneratedValue
    private Long id;

    public AddressEntity(Address address){
        this.address = address;
    }

    @Embedded
    private Address address;

    public AddressEntity(){
        }

    public AddressEntity(String city, String street, String zipcode) {
        this.address = new Address(city, street, zipcode);

    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}

 

Dto를 만들어 사용하는 것이 안전해! 

Entity에서 직접 가져와 변형 시키지 말고 DTO를 만들어서 조작하자!

            //값 타입 수정
//            // homecity = > newCity
//            Member member = new Member();
//            Member findMember = em.find(Member.class, member.getId());
//            Address a = findMember.getHomeAddress();
//            findMember.setHomeAddress(new Address("newCity", a.getStreet(), a.getZipcode()));
//
//            findMember.getFavoriteFoods().remove("치킨");
//            findMember.getFavoriteFoods().add("한식");
//            findMember.getAddressHistory().remove(new AddressEntity("old1", "street", "10000"));
//            findMember.getAddressHistory().add(new AddressEntity("newCity", "street", "10000"));

가장 좋은 방법

=> 임베디드, Collection 같은 값 타입은 여러 Entity에 공유되는 순간 큰 일이 나기 때문에.

Entity로 변경해서 사용하자!!!

 

 

반응형

'[WEB]Back-end > JPA' 카테고리의 다른 글

JPQL이 뭐야? 어떻게 사용해?  (0) 2022.01.21
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 전략  (0) 2022.01.21
Embedded 타입  (0) 2022.01.17
영속성 전이 :CASCADE  (0) 2022.01.17
Proxy 어떻게 최적화해?  (0) 2022.01.14
Comments