JPA 스터디 7주차

반응형
반응형

이번주에 진행할 주제는 값 타입이다. 
이번장에서 가장 중요한 키워드는 '공유'라고 생각한다.

자바에는 수 많은 타입들이 존재한다.
기본형, 객체형 ..까지 다양한 타입들이 존재한다.
이들에 대해 자세하게 설명하고 싶지만 
글이 길어질 수 도 있기 때문에 작성하지는 않을 예정이다.
아무튼 
기본형 같은 경우는 공유가 되지 않는다.
int a = 10이고
int b = 20일때 b =a // a = 30를 했을 경우에는 어떻게 될까?
바로 b = 10이 되버린다. 이는 공유가 된것이 아니라 값 자체가 복사가 되서 발생한 결과다.
그러니까 b의 입장에서는 20이라는 값이 의미가 없어지고 a의 값이 복사가 되서 그 값을 이용한다.

다른 타입들은 어떨까?
이거는 약간의 실습이 필요 하다.

Box boxA = new Box();
boxA.setValue(5);
Box boxB = boxA;
System.out.println("A box value : " + boxA.getValue());
System.out.println("B box value : " + boxB.getValue());
boxB.setValue(10);
System.out.println("A box value : " + boxA.getValue());
System.out.println("B box value : " + boxB.getValue());

a의 값과 b의 값은 어떨까?
같을까 다를까 실행해보자.

A box value : 5
B box value : 5
A box value : 10
B box value : 10

놀랍게도 값이 똑같이 나왔다.
첫번째는 그렇다고 치지만 두 번째는 두 개의 클래스가 서로 공유했다고 밖에 말하지 못할것 같다.
그거 말고는 설명할 방법이 전혀 없을 것 같기 때문이다.

그렇다면 JPA에서는 어떤 타입을 사용할까?

사실 두 가지 모두 사용이 되어진다.
기본형이나 객체형이나
근데 기본형같은 경우는 공부했던 것에 해답이 존재한다.

그러니까 내가 말하고 싶은 건 객체형이다.
근데 이 객체형을 리스트 같은 컬랙션에 저장한다는 건 아니고

public class Box {
  private int value;
  private Box2 box;
}

 요렇게 객체안에 객체를 넣는 뭐 그런 느낌이다.
여기에는 문제가 있다.
그건 이걸 엔티티로 만드는 경우 JPA입장에서는 1:1 혹은 다:1 관계로 이해를 할것이다.
하지만 나는 이곳은 엔티티로 만들고 싶지 않는 경우라면?
당연한 이야기겠지만, error가 발생 된다.

그러면 방법이 없는 걸까?
다행히도 JPA는 이러한 문제를 해결하기 위해 방법을 제공하고 있다.
바로 @Embeddable, @Embedded를 이용하면 된다. 이 어노테이션들을 이용해서 xToOne으로 하는게 아닌 순수한 객체로
이용한다는 것을 JPA한테 알려주는 목적을 가지고 있다.

저것들이 뭔지는 일단 보면은 바로 이해가 된다고 생각한다.

@Embeddable
public class PhoneNumber {
  private String areaCode;
  private String localNumber;

  @ManyToOne PhoneServiceProvider provider;
}
@Entity
public class Member {

  @Id
  @GeneratedValue
  private Long id;
  private String name;
  @Embedded
  private PhoneNumber phoneNumber;
}

이것만 보고 이해가 되지 않을 것 같아 그림을 그려서 확인해보자.

요런 시스템이다. 결국 phone number라는걸 Member뿐만 아니라 다른 곳에서도 사용이 가능하다.
Admin이 있다면 Admin에도 적용하고 ... 뭐 이런 느낌이다.

단순히 값만 존재하는 경우보다 훨씬 객체 지향처럼 만들 수 있다.
더 놀라운 사실은 이곳에서도 다:1같은 관계를 적용할 수 있다는 점이다.
속성을 재 정의하는 방법도 있지만, 그것은 굳이 작성할 필요가 없을 것 같아 생략한다.

근데 맨 처음에 이번장에서 가장 중요한 키워드는 '공유'라고 한적이 있다.
그 이유가 무엇일까?

A box value : 5
B box value : 5
A box value : 10
B box value : 10

이러한 현상이 DB에도 나타난다는 이야기인데
이렇게 되버리면 내가 수정할려고 안했는데 같은 객체를 쓴다는 이유 하나만으로 원치 않는 값이 들어 올 수 있다.

어떻게 하면 이것을 막을 수 있을까?
1. 클래스에 final을 붙여서 클래스가 변경이 되지 않도록 유도한다.
2. 같은 객체를 사용하지 않도록 항상 객체를 새로 만들어서 사용한다.

이 두 가지 규칙만 정해도 위와 같은 이상현상은 막을 수 있다.
첫번째 같은 경우는 직접적으로 막는다기 보다는 객체가 수정되는것을 막기 위한 방법이라 생각하면 된다.
또한 인간의 실수를 조금이라도 줄이는 방법이라 생각한다. 왜냐하면 객체를 수정하게 되면 컴파일에러가 발생하기 때문이다.

테스트를 조금 진행해봤는데 final을 왜 붙이지? 상속을 막기 위해서인가?
테스트안해봤으면 맞다고 생각할 뻔했네

 Member memberA = new Member();
      Address address = new Address();
      address.setCity("서울");
      address.setState("1-1");
      address.setStreet("회안대로");
      address.setZipCode(null);
      memberA.setAddress(address);
      em.persist(memberA);
      address.setCity("경기도");
      memberA.setAddress(address);
      em.persist(memberA);

      Member memberB = new Member();
      Address addressB = address;
      address.setCity("강원도");
      memberB.setAddress(addressB);
      em.persist(memberB);
      tx.commit();


내가 이런식으로 저장했는데
결과는

ID  	COMPANY_CITY  	STATE  	STREET  	PLUSFOUR  	ZIP  	NAME  	AREACODE  	LOCALNUMBER  	PROVIDER_NAME  
1	강원도	1-1	회안대로	null	null	null	null	null	null
2	강원도	1-1	회안대로	null	null	null	null	null	null
(2 행, 5 ms)

이렇게 나온다. 나는 memberB를 한번도 강원도로 바꾼적이 없다. 이러한 이유때문에 
같은 객체를 사용을 금지하는거라 생각이 든다.

      Member memberB = new Member();
      Address addressB = new Address();
      addressB.setCity("강원도");
      addressB.setStreet("강남역 1번 출구");
      memberB.setAddress(addressB);
      em.persist(memberB);
      addressB.setCity("경상도");
      em.persist(memberB);

요걸 이렇게 변경하고 실행해보면

ID  	COMPANY_CITY  	STATE  	STREET  	PLUSFOUR  	ZIP  	NAME  	AREACODE  	LOCALNUMBER  	PROVIDER_NAME  
1	경기도	1-1	회안대로	null	null	null	null	null	null
2	경상도	null	강남역 1번 출구	null	null	null	null	null	null

서로가 간섭하지 않고 객체가 변경이 된다는 것을 알 수 있다.

따라서 결론은
1. 객체지향처럼 엔티티를 구축하고 싶다면 @Embeddable, @Embedded를 활용하자.
2. 같은 엔티티를 2번이상 사용하지 말자.
     

반응형

'JPA' 카테고리의 다른 글

쿼리 메소드 기능(2)  (0) 2022.04.05
쿼리 메소드 기능(1)  (0) 2022.04.01
JPA 스터디 6주차  (1) 2022.02.20
JPA 스터디 5주차  (0) 2022.02.11
JPA 스터디 4주차  (0) 2022.02.02

댓글

Designed by JB FACTORY