-
12. 데이터 타입 분류웹개발/Hibernate(JPA) 2020. 5. 1. 16:47
안녕하세요 현우입니다. 이번 포스팅은 [ JPA에서 사용되는 데이터타입의 분류 와 자세한 설명 ] 입니다.
JPA 학습에 도움을 주신 김영한 개발자님과 김성인 개발자님에게 항상 감사드립니다 :)
참고서 http://acornpub.co.kr/book/jpa-programmig
엔티티타입
@Entity로 정의 하는 객체이며 데이터가 변해도 식별자로 지속해서 추적이 가능하다. 예를들어 회원의 키와 나이값을 전부 변경한다고 해도 PK값으로 추적이 가능하다.
값타입 분류
- 기본값타입
int, Integer, String처럼 단순히 값으로 사용하는 자바 기본타입이나 객체이다. 식별자가 없고 값만 있으니 당연히 추적이 불가능하다 즉 숫자를 100에서 200으로 변경하면 완전히 다른 값이 되버린다.
생명 주기가 엔티티에 의존되있어 회원엔티티를 삭제하면 이름,나이 필드도 함께 삭제된다. 값타입은 절대 공유하면 안된다. 즉 회원의 이름 변경시 다른 회원의 이름도 당연히 변경되면 안된다.
int, double은 절대로 공유가 불가능하기 때문에 기본값 타입으로 쓰기에 안정적이다. 반대로 Integer같은 래퍼 클래스나 String 같은 특수한 클래스는 공유 가능한 객체이지만 변경이 불가능하다.
int a = 10; inb b = a; a = 20; sout(a,b) = 20,10 // 값이 변경이 안된다. ********************************************* Integer a = new Integer(10); Integer b = a; public void setValue(int a){ this.a = a; } a.setValue(20); sout(a,b) // 레퍼런스를 공유하기 때문에 둘다 같은 값이 출력된다.
- 임베디드타입
새로운 값 타입을 직접 정의 할 수 있고 JPA는 이를 임베디드 타입이라고 한다. 주로 기본값 타입을 모아서 만들어서 복합 값 타입이라고도 하며 int, Stirng과 같은 값 타입이라고 보면된다. (엔티티 x, 추적이안된다)
예를 들어서 회원 엔티티에 이름, 근무시작일, 근무종료일, 주소도시, 주소 번지, 주소우편번호를 가질때 이중 몇몇 컬럼값을 내 시스템이서 공통으로 쓸수 있지 않을까?
두개의 클래스를 만들어 주어서 사용한다.
JPA
- @Embeddable : 값 타입을 정의하는 곳에 표시
- @Embedded : 값 타입을 사용하는 곳에 표시
장점
- - 재사용이 가능하다 (기간, 주소 등 시스템내 어디서든 사용이 가능)
- - 높은 응집도
- - Period.isWork() 처럼 해당 값 타입만 사용하는 의미 있는 메소드를 만들 수 있다. 객체지향적으로 설계가능
- - 임베디드 타입은 값타입을 소유한 엔티티에 생명 주기를 의존한다.
테이블에서 매핑은 임베디드 타입 사용유무와 무관하다.
임데디드 타입은 단순이 엔티티 값일 뿐이며 사용하기 전과후 매핑테이블은 똑같다(DB에영향이없다) 객체와 테이블을 아주 세밀하게 매핑하는 것이 가능하며 , 잘 설계한 ORM애플리케이션은 매핑한 테이블의 수보다 클래스의 수가 더 많게 된다.
PhoneNumber은 반대로 PhoneEntity를 가질수있다. 당연하다 FK값을 가지고 있기 때문에,
엔티티 클래스 안에서 pirvate Phone phone; 선언이 가능하단 얘기다.
만약 컬럼의 이름이 같다면 ?
@AttributeOverrides를 사용하여 컬럼명을 재정의 해주면된다.
값 타입 공유참조
임베디드 타입 같은 값 타입을 여러 엔티티에서 공유가 가능하다. 임베디드의 값을 변경할때 임베디드를 참조하고 있던 모든 엔티티도 같이 변경된다.
첫번째 member변수의 주소를 바꾸기 위해 member.getHomeAddress().setCity("newCity"); 를 하였다.
이때 전부 바뀌는걸 볼 수 있다. 이러한 버그는 잡기가 매우힘들다. 이렇게 임베디드타입을 여러곳에서 공유할 경우 sideeffect 가 발생한다.
그러므로 대신 인스턴스를 복사해서 사용한다.
Address address = new Address (city, name,...) ; //member에 들어갈값
address copyAddress = new Address(getCity, getName) // 복사한 값을 member2에 넣어준다.
하지만, 실수로 memeber2.setAddress(address), 즉 중복된 값으로 셋팅했다면??
항상 값을 복사해서 사용하면 공유참조로 인한 부작용을 피할수 있지만, 임베디드타입처럼 직접 정의한 값 타입은 자바의 기본 타입이 아니라 객체 타입이다. 객체 타입은 참조값을 직접 대입하는 것을 막을 방법이 없다. 객체의 공유참조는 피할수가없다. 타입이 같을 경우 어떻게든 값이 들어간다...
불변화
불변이라는 작은 제약으로 큰재앙을 막을 수 있다.
그러므로 생성자에서 값이 정해지면 변할수없게 setxxx메소드를 전부 지우고 getxxx만 남긴다
실제로 값을 바꾸고 싶을땐 HomeAddress를 newAddress로 완전히 다시 세팅해주어야 한다.
값 타입 컬렉션
엔티티클래스에서 값을 List 혹은 set 과같은 컬렉션 타입으로 선언할 경우 데이터베이스는 어떻계 설계 해야할까
컬렉션으로 선언한 컬럼용 데이터베이스를 만들어 줘야한다. DB안에 컬렉션을 같은 테이블에 저장할 수 없다. 일 대 다관계를 사용하여 별도의 테이블로 풀어내야 한다.
@ElementCollection
@CollectionTable
JoinColumn 을 외래키로 잡는다
값 넣어주기.
em.persist(member) 만 저장해도 값타입 컬렉션으로 지정된 다른테이블도 함께 저장되는 것을 볼수 있다. 컬렉션으로 선언한 테이블은 라이프사이클을 본인이 아니라 선언되어진 member클래스에게 있다. . 즉 값 타입 컬렉션은 영속성 전이와 고아객체 제거기능을 필수로 가진다고 볼 수 있다.
조회
값을 조회하면 member의 컬럼 값만 조회된 것을 확인할수 있다. 즉 컬렉션 타입은 지연 로딩임을 확인할 수 있다.
for loop을 사용하여 직접 조회해야저 insert쿼리문이 나가는걸 볼 수 있다.
코드자세히보기
https://github.com/HyeonWuJeon/KimYoungHan-JPA
'웹개발 > Hibernate(JPA)' 카테고리의 다른 글
13. JPA에서 사용하는 다양한 쿼리 방법 (0) 2020.05.07 11. 영속성 전이(CASCADE)와 고아 객체 (0) 2020.04.28 10. 즉시 로딩과 지연 로딩 (0) 2020.04.28 9. 프록시와 연관관계 (0) 2020.04.25 7. 고급매핑 (0) 2020.04.20