-
[Spring] Spring Data JPA의 save 함수 구조Spring 2022. 6. 17. 21:09
Spring Data JPA의 save함수의 구조는 다음과 같다.
public <S extends T> S save(S entity) { if (entityInformation.isNew(entity)) { // 1 em.persist(entity); // 2 return entity; // 3 } else { // 4 return em.merge(entity); // 5 } }
1번의 isNew 함수를 통해 매개변수로 들어온 entity가 새로운 entity인지, 이미 저장된 entity인지 체크한다.
- 레퍼런스 타입(String, Long...)일 경우 null값이면 새로운 entity로 판단한다.
- 기본 타입(Primitive Type)[int, long, char etc..]일 경우 값이 0이면 새로운 entity로 판단한다.
따라서 id 생성 방식이 @GeneratedValue이라면 엔티티가 저장되기 전에는 id값이 null이거나 0이기 때문에 2번, 3번을 차례로 진행한다.
2번과정을 진행한 entity의 id값에는 @GeneragedValue 속성에 맞게 값이 채워져 있다.
그렇다면 id값이 @GeneratedValue방식이 아니라 사용자가 직접 입력하는 값이라면 어떤식으로 판별할까
우선 아무런 설정이 되있지 않다면, id값에는 보통 값이 채워져 있을 것이기 때문에, 1번구간을 넘어가지 못하고 4번으로 넘어가 merge를 하게 된다.
merge을 하게 될 경우 해당 entity가 데이터베이스에 존재하는지 체크하기 위해 select 쿼리가 한번 발생하게 된다.
insert가 발생하기 전 select가 한번 발생하는 것을 볼 수 있다.
이렇게 @GeneratedValue을 쓰지 않은 채로 별다른 설정이 없으면 매 저장시마다 Select 쿼리가 한번씩 발생할 수 밖에 없다.
이를 위해 다음과 같이 문제를 해결할 수 있다.
@Entity @Getter @EntityListeners(AuditingEntityListener.class) @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Movie implements Persistable<Long> { @Id @Column(name="movie_id") private Long id; private String title; private String thumbnail; private String directorName; private Integer year; private String naverUrl; private String nation; private Double popularity; private String actors; @CreatedDate @Column(updatable = false) private LocalDateTime createdDate; private LocalDateTime lastModifiedDate; @Override public boolean isNew() { return getCreatedDate() == null; } }
해당 entity에 Persistable<id타입>을 상속받아 isNew을 커스텀할 수 있는 방법이 있다.
이를 이용해 createDate이나 다른 기타 판별방식을 활용해 select 쿼리를 안나갈 수 있도록 할 수 있다.
'Spring' 카테고리의 다른 글
[Spring boot] spring boot batch 관계도 (0) 2022.05.10 [Spring boot] spring boot batch 기본 구조 (0) 2022.05.04 [Spring] Swagger 2.9.2 Jwt 설정 통일하는 법 (0) 2022.03.31 [Spring] Swagger 2.9.2 NumberFormatException 해결법 (0) 2022.03.31 [Spring] Spring Security 로그인된 유저 뽑아오기 (1) 2022.03.14