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

By | 2021년 1월 19일
Table of Content

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)));
    }

답글 남기기