Back-End/JPA

[JPA] 7. 값 타입

imsongkk 2022. 8. 12. 01:26

JPA의 데이터 타입

 

JPA의 데이터 타입은 Entity 타입과 값 타입, 2가지로 나뉜다

 

Entity 타입은 기존에 @Entity Annotation으로 수식해주는 객체이고, 

 

Id를 가지고 있어 직접 DB 테이블에 매핑된다

 

 

값 타입은 int, Integer, String 처럼 단순히 값으로 사용되는 자바 기본 객체를 칭한다

 

엔티티에 속하므로 생명주기는 엔티티에 의존하게 된다

 

@Entity
public class Member {
	private String text; // Member가 사라지면 당연히 text도 사라진다!
}

 

임베디드 타입

 

값 타입에는 기본 값 타입 이외에도 임베디드 타입(복합 값 타입)이 있는데

 

프로그래머가 새롭게 정의한 객체라고 생각하면 된다.

 

예를들어 Member가 다음과 같은 필드(값 타입)를 가질때,

 

 

연관성이 있는 필드들 끼리 묶어서 새로운 값 타입으로 정의할 수 있다

 

마치 순수 Java에서 가독성을 위해 여러 필드들을 포함하는 새로운 클래스로 만드는것과 같다

 

 

 

Period와 Address 는 Primitive 값 타입이 아닌 Embedded 타입이므로,

 

Column에 매핑될 수 없고 따로 고유한 테이블이 있어야 한다.(마치 엔티티 처럼)

 

Embedded 타입을 사용했을 때의 장점은 다음과 같다

 

  • 재사용성
    • 필드조합을 새롭게 클래스단으로 분리시키므로 재사용이 용이해진다
  • 높은 응집도
    • 관련있는 필드들끼리 묶고 심지어 함수도 안에 정의할 수 있으므로 데이터들간의 연관성이 늘어난다
  • 값 타입을 소유한 엔티티의 생명주기를 따라간다
    • 따로 관리해줄 필요가 없다!

 

Embedded 타입을 가지는 Entity 객체를 DB 테이블에 매핑하면 다음과 같아진다

 

 

잘 보면 원래 버전의 DB Table과 달라진점이 하나도 없는것을 볼 수 있다

 

Embedded 타입은 특별한 것이 아닌 그저 Entity 객체의 필드값이다.

 

Embedded 타입을 사용하더라도 Table 구조 자체가 바뀌는것이 아니며 오직 프로그래머의 편의를 위해서 존재한다

 

 

값 타입 공유 참조

 

다음과 같은 상황을 생각해보자

 

 

 

@Entity
public class Member {
	@Embedded // 값 타입을 사용하겠다고 명시
	public Address address;
}

@Embeddable // 값 타입을 정의하기 위한 명시
public class Address {
	public class Address(); // 기본 생성자가 필수이다
	public String city = "old city";
}

public static void Main() {
	Address address = new Address();
	Member member1 = new Member();
    member1.setAdress(address);
    
    Member member2 = new Member();
    member2.setAdress(address);
    member2.getAdress().setCity("new city");
    
    //member1의 주소도 바뀌게 된다!
}

 

객체의 참조성으로 일어나는 이러한 Side-Effect를 막기위해 다음과 같은 방법을 생각해볼 수 있다

 

public static void Main() {
	Address address = new Address();
	Member member1 = new Member();
    member1.setAdress(address);
    
    Address address2 = new Address(address.getCity());
    Member member2 = new Member();
    member2.getAdress().setCity("new city");
    
    //member1의 주소는 바뀌지 않는다!
}

 

의도대로 동작하긴 하지만 이것도 프로그래머의 실수로 인해

 

새로운 객체 선언 및 초기화를 까먹는다면 예기치 못한 Side-Effect를 만들 수 있다

 

 

 

따라서 가장 완벽한 방법은 값 타입은 아예 불변 객체로 설계하는 것이다

 

public class Address {
	public Address(String _city) {
    	city = _city;
    }
	private String city = "old city";
    
    // 생성자 주입으로만 값을 변경할 수 있다.
    // Setter는 없거나 있어도 private으로 설정
}

 

 

 

출처 : https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com