백엔드
[Spring Boot] JPA 값 타입
육빔
2024. 9. 2. 17:39
728x90
반응형
JPA의 데이터 타입은
엔티티 타입
값 타입
으로 구분 할 있다.
여기서 엔티티 타입은
우리가 @Entity를 붙이는 객체를 말하는 거고
값 타입은 자바 기본 타입이나 객체를 말한다.
1. 값 타입의 종류
JPA에서 값 타입은 크게 세 가지로 나눌 수 있습니다.
- 기본 값 타입(Basic Value Type)
- JPA에서 제공하는 기본적인 값 타입으로, Java의 기본 데이터 타입(int, long, double, boolean 등)과 래퍼 클래스(Integer, Long, Double, Boolean 등), 그리고 String, Date, BigDecimal, BigInteger 같은 타입들이 이에 해당합니다.
- 별도의 매핑 없이 엔티티의 속성으로 사용 가능하며, 데이터베이스 테이블의 컬럼과 직접적으로 매핑됩니다.
- 임베디드 타입(Embedded Type)
- 임베디드 타입은 여러 속성을 하나의 객체로 묶어서 사용하는 복합 값 타입입니다.
- Java 클래스 형태로 정의되며, 이 클래스는 엔티티에 포함되어 재사용될 수 있습니다.
- @Embeddable 어노테이션을 사용하여 임베디드 타입을 정의하고, 엔티티에서는 @Embedded 어노테이션으로 이를 사용합니다.
@Embeddable
public class Address {
private String city;
private String street;
private String zipcode;
}
@Entity
public class Member {
@Id
private Long id;
@Embedded
private Address address;
}
3. 컬렉션 값 타입(Collection Value Type)
- 값 타입 컬렉션은 임베디드 타입이나 기본 값 타입을 여러 개 모아서 사용할 때 사용됩니다.
- 주로 List, Set, Map 등의 컬렉션 형태로 사용되며, 컬렉션에 담긴 값 타입들은 JPA 엔티티의 일부분으로 간주됩니다.
- 데이터베이스에서는 값 타입 컬렉션이 별도의 테이블로 매핑됩니다
@Entity
public class Member {
@Id
private Long id;
@ElementCollection
@CollectionTable(name = "favorite_foods", joinColumns = @JoinColumn(name = "member_id"))
@Column(name = "food_name")
private Set<String> favoriteFoods = new HashSet<>();
}
또한 이런 값 타입을 사용할때 주의점이 있다.
1. 값 타입의 공유 참조 문제
- 공유 참조의 위험성: 값 타입을 여러 엔티티에서 공유하면 위험할 수 있습니다. 예를 들어, 두 엔티티가 같은 주소(Address) 객체를 참조하면 한 엔티티에서 주소를 변경할 때 다른 엔티티의 주소도 의도치 않게 변경될 수 있습니다. 이것은 **부작용(side effect)**을 초래할 수 있습니다.
- 값 복사: 값 타입의 인스턴스를 직접 공유하지 않고 복사해서 사용해야 부작용을 방지할 수 있습니다. Java의 기본 타입(int, float 등)은 값을 대입할 때 복사되지만, 객체 타입(예: Address)은 참조 값(레퍼런스)이 전달되므로 직접적으로 복사되지 않습니다.
2. 불변 객체의 필요성
- 불변 객체의 정의: 불변 객체(Immutable Object)는 생성된 이후로 상태가 변경될 수 없는 객체입니다. 한 번 값을 설정하면 그 값을 절대 바꿀 수 없습니다. 따라서 불변 객체는 수정이 불가능하므로 부작용을 원천적으로 차단할 수 있습니다.
- 불변 객체의 장점: 불변 객체는 값을 공유하더라도 그 값을 변경할 수 없기 때문에, 부작용이 발생하지 않습니다. 이는 값 타입을 안전하게 사용할 수 있는 방법입니다.
- 불변 객체의 구현: 불변 객체를 만들기 위해서는 객체의 모든 필드를 final로 선언하고, 생성자에서만 값을 설정하며, 이후에 값을 변경할 수 있는 메서드(수정자, setter)를 제공하지 않습니다.
@Embeddable
public class Address {
private final String city;
private final String street;
private final String zipcode;
public Address(String city, String street, String zipcode) {
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
public String getCity() {
return city;
}
public String getStreet() {
return street;
}
public String getZipcode() {
return zipcode;
}
}
728x90
반응형