Dev 달팽이 @_''

[JPA] Entity Default Value 삽입(DynamicInsert) 본문

Java&Spring/JPA

[JPA] Entity Default Value 삽입(DynamicInsert)

다본죽 2022. 9. 20. 19:03

서론

프로젝트를 하다보면 Entity에 Default Value 값을 지정하는 경우가 자주 있습니다. 이럴 경우 매번 Entity를 생성할 때 직접 Default 값을 넣어주었는데 이번 사이드 프로젝트에서는 다른 방법을 사용해 보았습니다.

 

환경 : Java 11, MySQL, Springboot

 

준비

간단하게 Entity는 Product만 준비했습니다. 이번 예제에서 Default Value를 사용하는 칼럼은 삭제 여부를 체크하는 isDeleted와 생성 시간을 담는 createdAt 입니다.

Product.class

package com.example.jpatest;

import java.time.LocalDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.DynamicInsert;

@Entity
@Getter
@DynamicInsert
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Product {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "product_id")
  private Long id;

  @Column(nullable = false, length = 45)
  private String name;

  @Column(nullable = false)
  private Integer price;

  @Column(nullable = false, length = 100)
  private String description;

  @Column(columnDefinition = "0")
  private Boolean isDeleted;

  @Column(columnDefinition = "CURRENT_TIMESTAMP")
  private LocalDateTime createdAt;

}

ProductDto.class

package com.example.jpatest;

import lombok.Getter;

@Getter
public class ProductDto {

  private String name;

  private Integer price;

  private String description;

  public Product toEntity() {

    return Product.builder().name(name).price(price).description(description).build();

  }

}

ProductService.class

package com.example.jpatest;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class ProductService {

  public final ProductRepository productRepository;

  public void insertProduct(ProductDto productDto) {

    Product product = productDto.toEntity();
    productRepository.save(product);

  }

}

 

테스트

ProductServiceTest.class

package com.example.jpatest;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class ProductServiceTest {

  @Autowired
  private ProductService productService;

  @Test
  void insertProduct() {

    ProductDto productDto1 = new ProductDto("product1",3000,"product1 description");

    productService.insertProduct(productDto1);

  }
}

Hibernate 쿼리 확인

@DynamicInsert 를 썻을 경우

실제 값이 들어간 칼럼만 들어간 것을 확인 할 수 있다.

@DynamicInsert 를 안썻을 경우

당연히 결과는 에러가 나고 값이 들어가지 않은 컬럼에 insert를 넣지 않은 부분은 null이 들어가는 걸 알 수 있습니다.

 

마무리

처음에 Entity를 정의할 때, columnDefinition을 사용하면 알아서 정해놓은 Default Value가 들어간다고 생각했습니다. 하지만 이는 테이블을 생성할 때 제약조건을 걸어주는 것이었습니다.

DynamicInsert를 사용하기 전에는 Entity를 생성할 때 직접 Default Value를 넣어줬는데 이보다 DynamicInsert를 사용하는 것이 성능상으로도 더 좋습니다.

DynamicInsert 말고도 Update에 사용하는 DynamicUpdate도 존재합니다.

 

columnDefinition과 DynamicInsert를 혼동해서 사용하지 말자!

직접 Default Value를 넣어주는 것보다 DynamicInsert를 사용하는 것이 더 좋은 성능을 낸다! 

 

참고 : https://mangchhe.github.io/jpa/2021/09/06/EntityDynamicQuery/