JPA 기본값, 변경된 필드만 업데이트

By | 2021년 1월 19일
Table of Contents

JPA 기본값, 변경된 필드만 업데이트

JPA 기본값

@ColumnDefault("0")@Column(nullable = false) 는 테이블 스키마 생성에만 관여한다.

insert 값이 null 인 경우 기본값으로 자동입력 해주는 기능은 없다.

private Integer likeCount = 0; 과 같이 기본값을 설정해 주어야 한다.

@Entity
@Getter
@Setter
@Table(name = "MEDIA")
@NoArgsConstructor
public class Media {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "idx")
    private Long idx;

    @ColumnDefault("0")
    @Column(nullable = false)
    private Integer likeCount = 0;

    @NotNull
    @ColumnDefault("0")
    private BigDecimal price = BigDecimal.ZERO;

    @Builder
    public Media(Integer likeCount) {
        this.likeCount = likeCount;
    }
}

@Column(nullable = false) 은 테이블 스키마 생성에만 관여한다.

null 값 체크는 실제로 insert 하는 시점에 DB 에서 체크된다.

@NotNull 은 DB 에서 체크되는 것이 아니라, JPA 에서 체크된다. 또한 아래 의존성이 추가되어야 한다.

dependencies {
    // ......
    compile('org.springframework.boot:spring-boot-starter-validation')
    // ......
}

변경된 필드만 업데이트

JPA 는 null 값이 명시적으로 null 값으로 설정하는 것인지 아니면 단지 값을 입력하지 않아 null 인지를 구분하지 못한다.

변경이 필요한 필드를 업데이트 하려면, PK 를 이용에 Entity 전체를 불러와서, 변경이 필요한 필드를 명시적으로 업데이트(코딩)해야 한다.

null 이 아닌 필드만 업데이트 하기

mapstruct 를 이용해 null 이 아닌 필드만 업데이트 할 수 있다.

아래의 의존성이 추가로 필요하다.

dependencies {
    // ......
    implementation 'org.mapstruct:mapstruct:1.4.1.Final'
    annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.1.Final'
    // ......
}

Dto 는 반대로 디폴트 값 설정을 하면 안된다.

@Setter
@Getter
@NoArgsConstructor
public class MediaDto {

    private Long idx;
    private Integer likeCount;
    private BigDecimal price;
}

매핑시 null 인 필드를 무시한다.

@Mapper(componentModel = "spring")
public interface MediaMapper {

    @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
    void updateMediaFromDto(MediaDto dto, @MappingTarget Media entity);
}
    @Test
    public void test2() {

        Media media = new Media();
        Media resultMedia = mediaRepository.save(media);

        MediaDto mediaDto = new MediaDto();
        mediaDto.setPrice(BigDecimal.valueOf(5000));

        mediaMapper.updateMediaFromDto(mediaDto, resultMedia);
        Media resultMedia2 = mediaRepository.save(media);

        MatcherAssert.assertThat(resultMedia2.getPrice(), Is.is(BigDecimal.valueOf(5000)));
    }

2 thoughts on “JPA 기본값, 변경된 필드만 업데이트

  1. Truestar

    포스팅 잘 읽었습니다. Mapstruct 적용중에 의문이 잇어 글을 남기게 되었어요.
    Mapper 를 Dto 나 Entity 내부에 포함한 다음, toDto() 또는 toEntity() 로 반환되게 하는 방식은
    특별한 문제가 있을까요? Entity 매핑의 경우는 ENtityManager 가 포함된 매퍼 라야 하는 제한은 있습니다만..
    toXxxx() 방식에 문제점이 어떤게 있을지 의견이 궁금합니다.

    1. skyer9 Post author

      매퍼 객체를 매번 생성하면 하나만 있으면 되는 매퍼 객체가 여러개 생기게 되고
      매퍼 객체 참조를 세팅하면 매퍼 객체가 여러군데로 퍼지게 될 듯 하네요.

      가독성 면에서도 서비스 객체에 하나만 두는게 깔끔하긴 해요.

답글 남기기