소소한개발팁
article thumbnail
반응형

1. 기본값과 래퍼 클래스

1.1. 데이터 유형

 기본 값 (Primitive Values): 기본 데이터 유형은 자바에서 제공하는 8개의 기본 데이터 유형으로 이루어져 있습니다. 이러한 데이터 유형에는 int, float, boolean, char 등이 포함됩니다. 이러한 데이터 유형은 소문자로 작성됩니다.

래퍼 클래스 (Wrapper Classes): 래퍼 클래스는 기본 값에 대한 객체 표현으로, 기본 데이터 유형을 감싼(wrapper) 클래스입니다. 예를 들어, Integer, Float, Boolean, Character 등이 있습니다. 이러한 클래스는 대문자로 시작하며, 기본 데이터 유형과 관련된 여러 유용한 메서드와 기능을 제공합니다.

 

1.2. 값의 초기화

기본 값 (Primitive Values): 기본 데이터 유형은 기본값으로 자동 초기화됩니다. 예를 들어, int의 기본값은 0이며, boolean의 기본값은 false입니다.

래퍼 클래스 (Wrapper Classes): 래퍼 클래스의 객체는 기본적으로 null로 초기화됩니다. 따라서 값을 설정하기 전에 null 체크를 해야 합니다.

 

1.3. 메서드 및 기능

기본 값 (Primitive Values): 기본 데이터 유형은 단순한 값으로 취급되며, 메서드나 추가 기능을 제공하지 않습니다.

래퍼 클래스 (Wrapper Classes): 래퍼 클래스는 객체이므로 메서드를 호출하고 기능을 수행하는 데 사용할 수 있습니다. 예를 들어, Integer 클래스는 문자열에서 정수로 변환하는 parseInt() 메서드와 같은 메서드를 제공합니다.

 

1.4. Nullable 여부

기본 값 (Primitive Values): 기본 데이터 유형은 항상 값을 가지며 null을 허용하지 않습니다.

래퍼 클래스 (Wrapper Classes): 래퍼 클래스는 객체이므로 null을 가질 수 있습니다. 이것은 값이 없음을 나타낼 때 유용합니다.

 

1.5. 컬렉션과 사용

기본 값 (Primitive Values): 기본 데이터 유형은 컬렉션 (예: List, Set, Map)에 직접 저장할 수 없으며, 래퍼 클래스를 사용해야 합니다. 래퍼 클래스 (Wrapper Classes): 래퍼 클래스는 컬렉션에 저장할 수 있으므로, 컬렉션에서 다루기 쉽습니다.

 

2. JPA에서 래퍼 클래스 사용 방법

2.1. 래퍼 클래스를 생성합니다.

<java />
@Embeddable public class Fruit { private String name; private String color; public Fruit() {} // 생성자를 통한 초기화 public Fruit(String name, String color) { this.name = name; this.color = color; } // Getter 메서드만 제공하고, Setter 메서드는 없음 public String getName() { return name; } public String getColor() { return color; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Fruit fruit = (Fruit) o; if (getName() != null ? !getName().equals(fruit.getName()) : fruit.getName() != null) return false; return getColor() != null ? getColor().equals(fruit.getColor()) : fruit.getColor() == null; } @Override public int hashCode() { int result = getName() != null ? getName().hashCode() : 0; result = 31 * result + (getColor() != null ? getColor().hashCode() : 0); return result; } }

JPA 스펙자체에서 생성자를 생성할 때 파라미터가 없는 기본 생성자 메서드가 필요합니다. ( 생성자가 별도로 존재하지 않는 경우 기본 값으로 들어가기 때문에 생성할 필요 없습니다. 기본 생성자 이외에 생성자가 존재할 경우만 기본 생성자를 만듭니다.

래퍼 클래스는 값 자체가 아닌 값이 저장된 참조값을 저장하기 때문에 의도치 않게 값이 변경될 가능성이 존재합니다. 이를 방지하기 위해 Setter를 별도로 제공하지 않거나 Private로 정의하고 생성자를 통해서만 변경가능하도록 합니다.

생성된 래퍼클래스를 비교할 때 사용하기 위해 equals 와 hashcode를 생성하도록 합니다. 이때 프록시에서 래퍼클래스에 접근할 때 문제가 발생할 수 있으므로 getter를 이용하여 equals를 생성합니다.

 

2.2. 엔티티에서 래퍼 클래스를 접근합니다. 

<java />
@Entity public class Basket { @Id private Long id; private String owner; @Embedded private Fruit fruit; // Getters and setters // 다른 필드와 메서드 }

래퍼 클래스에 생성할 때 @Embeddable을 선언할 경우 별도로 @Embedded를 작성하지 않아도 되지만 명확하게 확인할 수 있어서 가져오는 필드에 @Embedded 어노테이션을 선언하도록 합니다.

 

반응형

 

3. 컬렉션 래퍼 클래스 

3.1. 사용방법

<java />
@Entity public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ElementCollection @CollectionTable(name = "order_fruits", joinColumns = @JoinColumn(name = "order_id")) private List<Fruit> fruits = new ArrayList<>(); // 다른 필드, 생성자, getter, setter 등 필요한 메서드 }

래퍼클래스를 컬렉션으로 묶은 값들을 사용할 때는 @ElementCollection 을 정의하고 @CollectionTable 을 선언한 후 테이블 이름 정의  후 Order 테이블과의 조인을 할 외래키 (order_id) 를 정의합니다. 외래키를 정의하는 이유는 관계형 데이터베이스에서는 테이블 안에 객체를 생성할 수 없기에 별도의 테이블을 생성하여 외래키로 연결하여야 하기 때문입니다. 하지만 이렇게 정의된 Fruit 테이블은 기본키가 존재하지 않아서 테이블에 접근하는 데 큰 문제가 있습니다. 그러므로 추적할 필요가 없는 단순한 데이터들의 묶음일때만 사용할 수 있도록 합니다.

 

3.2. 컬렉션 래퍼클래스 사용 시 단점에 대한 대체제 

<java />
@Entity public class FruitEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Embedded private Fruit fruit; // 생성자, getter, setter 등 필요한 메서드 } @Entity public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToMany(cascade = CascadeType.ALL,orphanRemoval = true) @JoinColumn(name = "order_id") private List<FruitEntity> fruits = new ArrayList<>(); // 생성자, getter, setter 등 필요한 메서드 }

 

CascadeType.ALL, orphanRemoval = true 와 컬렉션 래퍼클래스의 공통점

 

데이터 관리 및 관계 설정: 둘 다 엔티티 클래스와 관련된 데이터 모델을 정의하고, 엔티티 간의 관계를 설정하는 데 사용됩니다.

 

부모-자식 관계: 둘 다 부모-자식 관계를 나타내는데 사용됩니다. @OneToMany 관계는 하나의 부모 엔티티와 여러 개의 자식 엔티티 사이의 일대다 관계를 나타내며, 값 타입 컬렉션은 하나의 엔티티 내에서 여러 개의 값 타입을 컬렉션으로 관리합니다.

 

Cascade 옵션: 둘 다 CascadeType.ALL을 사용하여 부모 엔티티에 대한 변경 작업(저장, 수정, 삭제)을 자식 엔티티로 전파하도록 설정할 수 있습니다. 이렇게 설정하면 부모 엔티티의 변경이 자식 엔티티에 영향을 미칩니다.

 

orphanRemoval 옵션: 둘 다 orphanRemoval = true를 사용하여 부모 엔티티에서 자식 엔티티를 제거할 때 자식 엔티티를 데이터베이스에서 삭제하도록 설정할 수 있습니다. 이렇게 설정하면 자식 엔티티와 관련된 데이터를 데이터베이스에서 자동으로 삭제합니다.

 

일관성 유지: 둘 다 엔티티 간의 일관성을 유지하기 위한 방법으로 사용됩니다. 부모 엔티티와 자식 엔티티 간의 관계를 관리하고, 데이터베이스에서도 일관성을 유지합니다.

 

CascadeType.ALL, orphanRemoval = true 와 컬렉션 래퍼클래스의 차이점

 

@OneToMany 관계는 일대다 관계를 나타내며, 자식 엔티티는 별도의 엔티티로 정의되어 데이터베이스에 별도의 테이블로 저장됩니다. 반면 값 타입 컬렉션은 자식 엔티티를 별도의 엔티티로 정의하지 않고 부모 엔티티 내에서 값 타입의 컬렉션으로 저장됩니다. 따라서 값 타입 컬렉션은 자식 엔티티를 따로 조회하거나 관리하지 않으며, 데이터베이스에 별도의 테이블로 저장되지 않습니다.

 

반응형

'컴퓨터 언어 > Java' 카테고리의 다른 글

JPA - N+1 문제란?  (0) 2023.09.12
JPA - JPQL 사용 방법  (0) 2023.09.12
JPA - Proxy(프록시) 이해하기  (0) 2023.09.07
JPA - 상속 관계 및 MappedSuperclass  (0) 2023.09.07
JPA - 연관관계  (0) 2023.09.01
profile

소소한개발팁

@개발자 뱅

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!