티스토리 뷰

728x90
반응형

1️⃣ 기본 개념

@ElementCollection

  • JPA에서는 일반 엔티티가 아닌 값 타입(예: List<String>, Set<Enum> 등)을 저장할 때 사용합니다.
  • 별도의 테이블을 생성하여 관리합니다.
  • 예를 들어, 사용자(User)가 여러 개의 역할(Role) 을 가진다면, 역할을 따로 테이블에 저장해야 합니다.

fetch = FetchType.EAGER

  • EAGER(즉시 로딩) : User 엔티티를 가져올 때 즉시 함께 가져옴
  • 기본적으로 @ElementCollection은 LAZY이므로 명시적으로 EAGER로 설정하면 즉시 로딩됨

2️⃣ 예제 코드로 이해하기

👎 @ElementCollection 없이 일반적인 필드로 저장하면?

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String email;

    private String roles; // 🚨 여러 개의 역할을 `String`으로 저장하면 문제 발생

    // 예: "ROLE_USER,ROLE_ADMIN" 문자열로 저장하면 유지보수가 어려움
}

문제점:

  • roles를 String으로 저장하면 배열처럼 다루기 어려움
  • 새로운 역할이 추가될 때 수정이 어렵고 유지보수가 힘듦
  • SQL 검색이 불가능 (WHERE roles LIKE '%ADMIN%' 같은 쿼리는 비효율적)

👍 @ElementCollection을 사용하면?

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String email;

    @ElementCollection(fetch = FetchType.EAGER) // ✅ 별도 테이블로 저장 & 즉시 로딩
    @CollectionTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"))
    @Enumerated(EnumType.STRING)
    private Set<UserRole> roles = new HashSet<>();

    public enum UserRole {
        ROLE_USER, ROLE_ADMIN
    }
}

이제 역할을 Set<UserRole> 형태로 저장 가능!
✅ User 엔티티를 조회할 때 즉시 함께 가져오므로 추가적인 쿼리 실행 없이 사용 가능!


3️⃣ 실제 데이터베이스 테이블 구조

@ElementCollection을 사용하면 JPA가 자동으로 별도의 테이블을 생성합니다.

예를 들어, User 테이블과 별도로 user_roles 테이블이 생성됩니다.

| user 테이블 (users) | |----|------| | id | email | | 1 | user1@example.com | | 2 | user2@example.com |

| user_roles 테이블 |

user_id roles

1 ROLE_USER
1 ROLE_ADMIN
2 ROLE_USER

이제 여러 개의 역할을 개별적으로 저장할 수 있어 검색이 쉬워지고 유지보수도 편리해집니다.


4️⃣ fetch = FetchType.EAGER 의미

📌 EAGER(즉시 로딩) 설정을 하면 User 엔티티를 가져올 때 roles도 같이 가져옴!

User user = userRepository.findById(1L).get();
System.out.println(user.getRoles()); // 🚀 자동으로 roles도 가져옴!

📌 만약 FetchType.LAZY 로 설정하면? (@ElementCollection(fetch = FetchType.LAZY))

  • user.getRoles()를 호출할 때 추가 SQL 쿼리 실행됨
  • 성능 최적화가 필요한 경우 LAZY를 사용할 수도 있음

📌 정리

설정 설명

@ElementCollection 기본 엔티티가 아닌 "값 타입 컬렉션"을 저장할 때 사용
FetchType.EAGER User 엔티티를 조회할 때 roles 컬렉션을 즉시 로딩
FetchType.LAZY User 엔티티를 조회할 때 roles는 필요할 때만 로딩

🚀 즉시 로딩(FetchType.EAGER)은 작은 프로젝트나 자주 쓰이는 데이터에 적합하지만, 데이터가 많아지면 성능 문제를 초래할 수 있으므로 주의해야 합니다! 🚀

 


 

📌 @CollectionTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id")) 쉽게 설명하기

@CollectionTable은 JPA에서 @ElementCollection으로 정의된 값 타입 컬렉션을 별도의 테이블에 저장할 때 사용합니다.
즉, Set<String>이나 Set<Enum> 같은 값 타입을 엔티티와 독립적인 테이블에 저장하기 위한 설정입니다.


1️⃣ 왜 @CollectionTable이 필요한가?

만약 User 엔티티가 여러 개의 역할(Role)을 가질 수 있다면, 이를 테이블에 어떻게 저장할지 정의해야 합니다.
JPA에서 @ElementCollection을 사용하면 기본적으로 새로운 테이블이 생성되는데, 그 테이블의 이름과 매핑 방식을 설정하는 것이 바로 @CollectionTable입니다.


2️⃣ @CollectionTable 기본 예제

👀 예제 코드

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String email;

    @ElementCollection(fetch = FetchType.EAGER) // ✅ 값 타입 컬렉션 저장
    @CollectionTable(
        name = "user_roles", // ✅ 별도의 테이블 이름 설정
        joinColumns = @JoinColumn(name = "user_id") // ✅ User 테이블의 ID와 매핑
    )
    @Enumerated(EnumType.STRING) // ✅ Enum 값을 문자열로 저장
    private Set<UserRole> roles = new HashSet<>();

    public enum UserRole {
        ROLE_USER, ROLE_ADMIN
    }
}

주요 개념 정리

  1. @CollectionTable(name = "user_roles")
    user_roles라는 별도의 테이블에 roles 저장
  2. @JoinColumn(name = "user_id")
    User 테이블의 id와 연결하여 1:N 관계를 구성
  3. @Enumerated(EnumType.STRING)
    → Enum을 문자열 형태로 저장 (예: "ROLE_USER", "ROLE_ADMIN")

3️⃣ 실제 생성되는 데이터베이스 테이블

User 엔티티 테이블 (users)

id email

1 user1@example.com
2 user2@example.com

user_roles 값 타입 컬렉션 테이블

user_id roles

1 ROLE_USER
1 ROLE_ADMIN
2 ROLE_USER

이제 한 명의 유저가 여러 개의 역할을 가질 수 있으며, 별도의 테이블에서 관리되므로 검색과 유지보수가 용이합니다.


4️⃣ @CollectionTable을 사용하지 않으면?

@ElementCollection
private Set<UserRole> roles; // 🚨 테이블 이름을 설정하지 않으면 자동으로 생성됨!

📌 이 경우, JPA가 기본적으로 user_roles 테이블을 자동 생성하지만, 테이블 이름과 매핑 필드를 원하는 대로 지정할 수 없음.
📌 따라서, 실무에서는 @CollectionTable을 활용하여 테이블을 명확하게 정의하는 것이 좋습니다.


📌 결론

어노테이션 설명

@ElementCollection 값 타입 컬렉션을 저장하는 JPA 기능
@CollectionTable(name = "user_roles") 별도의 테이블(user_roles)에 저장하도록 설정
@JoinColumn(name = "user_id") users 테이블의 id와 연결하여 1:N 관계 형성

🚀 즉, @CollectionTable은 "값 타입 컬렉션을 위한 별도 테이블을 어떻게 생성할지"를 설정하는 기능입니다! 🚀

 

 

728x90
반응형