개요)
JPA에서 기본적인 어노테이션을 살펴보자
1. @ElementCollection
2. @FetchType.LAZY, @FetchType.EAGER
3. @EntityGraph
4. @GeneratedValue
[1. @ElementCollection]
이 어노테이션은
원하는 엔티티에서
칼럼 중 List를 넣고 싶을 때 사용한다
리스트 안에 요소는
Entity가 될 수 없다.
RDB에서는
리스트 형식의 자료구조가 없기에
테이블로 따로 저장된다.
해당 테이블은
FK로 엔티티와 묶인다.
아래 사진을 보자
UserRole은
ENUM형태로 필드값이 들어가 있다.
DB에는 어떻게 저장이 되는지 살펴보자
조회 했을 때
User 엔티티의
UserRole이 리스트형태로 들어가 있다.
[2. @FetchType.LAZY]
유저 엔티티 필드는 아래처럼 구성된다
[User.java]
package com.simple.project.domain;
import java.util.ArrayList;
import java.util.List;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Entity
@Table(name = "user")
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "userRoleList")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "uno")
private Long uno;
private String userId;
private String pw;
@ElementCollection(fetch = FetchType.LAZY)
@Builder.Default
private List<UserRole> userRoleList = new ArrayList<>();
public void addRole(UserRole userRole) {
userRoleList.add(userRole);
}
public void clearRole() {
userRoleList.clear();
}
public void changeUserId(String userId) {
this.userId = userId;
}
public void changePw(String pw) {
this.pw = pw;
}
}
아래 소스는
유저를 조회하는 조회문을 담당하는 메소드다
[UserRepository.java]
조회하면
아래의 쿼리로 조회된다.
User 엔티티의
UserRole은 왜 조회가 안될까?
UserRole은
@ElementCollection으로
외래키로 User테이블과 묶여 있지만
@FetchType.LAZY 으로 인해
쿼리로 바로 수행되지 않는다.
해당 객체에 접근이 감지되면
쿼리수행이된다.
debug 상태에서
user 데이터를 살펴보려고 커서를 올려다 놓는 순간!
추가 조회 되는 걸 볼 수 있다.
그렇다면
@FetchType.EAGER로 테스트해보자!
[3. @FetchType.EAGER]
유저 도메인에서
UserRole이 @ElementCollection으로
외래키로 묶여있다.
해딩 필드값 속성이
@FetchType.LAZY 일 때는
UserRole 데이터에 접근될 때만 쿼리가 조회되었다.
Eager일 때는 어떨까?
[User.java]
package com.simple.project.domain;
import java.util.ArrayList;
import java.util.List;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Entity
@Table(name = "user")
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "userRoleList")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "uno")
private Long uno;
private String userId;
private String pw;
@ElementCollection(fetch = FetchType.EAGER) //여기가 바뀜!
@Builder.Default
private List<UserRole> userRoleList = new ArrayList<>();
public void addRole(UserRole userRole) {
userRoleList.add(userRole);
}
public void clearRole() {
userRoleList.clear();
}
public void changeUserId(String userId) {
this.userId = userId;
}
public void changePw(String pw) {
this.pw = pw;
}
}
접근을 하든 안하든
바로 쿼리가 실행되어 조회한다.
@FetchType.EAGER는
@ElementCollection에 묶인 데이터에 접근 되든 안되든 바로조회!
@FetchType.LAZY는
@ElementCollection에 묶인 데이터에 접근 될 때만 조회!
음..
Join으로 쿼리 한번으로 조회 하려면 어떻게 해야할까?
그럴 땐 다음 방법으로 하면 된다!
[4. @EntityGraph]
[UserRepository.java]
package com.simple.project.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.simple.project.domain.User;
public interface UserRepository extends JpaRepository<User, Long> {
@EntityGraph(attributePaths = { "userRoleList" })
@Query("select u from User u where u.userId = :userId")
Optional<User> getUser(@Param("userId") String userId);
}
JPARespository에서
@EntityGraph 의 속성값인 attributePaths에
조인할 대상 테이블명을 넣어준다.
조회할 원래 테이블인
"User" 안에
attributePath의 대상테이블을 찾아
PK와 FK에 맞춰 Join 쿼리가 실행된다.
결과를 비교해보자
@EntityGraph는
조인을 해주는데
대상 테이블을 속성에 넣어줘야한다.
[4.@GeneratedValue]
@GeneratedValue는 기본 값이
Auto가 있고 IDENTITY가 있다.
@GeneratedValue.IDENTITY는
PK를 auto_increment로
자동으로 생성해준다.
'서버' 카테고리의 다른 글
SpringBoot3 - build.gradle에서의 구성과 의존성 차이 (0) | 2024.11.13 |
---|---|
iptime 공유기 초기화 후 설정(비밀번호 설정, 포트포워딩, WOL설정) (0) | 2024.11.03 |
nas) 시놀로지 - redis 설치 후 접속하기 (1) | 2024.10.24 |
nginx - react(cra) craco로 설정 후 청크 파일 경로 잘못된 오류 (0) | 2024.10.22 |
WYSIWYG - react(spa),Spring boot 3(JPA) 내용 정리 - 1(이미지업로드 처리방식@Lob,MEDIUMTEXT, axios 커넥션 지속기간 설정) (1) | 2024.10.16 |