JPA @ElementCollection 사용법

devdo·2024년 4월 7일
0

JPA

목록 보기
12/13
post-thumbnail

Product 엔티티


	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long pno;


    @ElementCollection
    private List<ProductImage> imageList = new ArrayList<>();

ProductImage

@Embeddable // 임베디드 할 수 있다는 걸 체크!
@Getter
@ToString
@NoArgsConstructor
public class ProductImage {

    private String fileName;

    @Setter
    private int ord;

    @Builder
    public ProductImage(String fileName, int ord) {
        this.fileName = fileName;
        this.ord = ord;
    }
}

실제 DB 상의 필드

product_image 테이블

특징

  • 값 타입 컬렉션은 자신의 라이프 사이클을 가지지 않는다.
    이것은 마치 영속성 전이(Cascade)와 고아 객체 제거 기능을 필수로 가진 것과 비슷하다고 볼 수 있다.

  • 또한 기본적으로 @ElementCollection이 LAZY로 설정돼 있어 지연로딩으로 작동한다.


만약 값 타입 컬렉션의 값을 수정하기 위해서는 어떻게 해야 할까?

값 타입 컬렉션 안의 데이터를 수정할 때는 일부만 수정하는 것이 아닌 데이터를 삭제 후 변경된 데이터 전체를 새로 추가해줘야 한다.

부모엔티티인 Product 내 그 로직이 담겨져 있다.

Product 엔티티 내 imageList 추가/수정 메서드

    public void addImage(ProductImage image) {
        if(this.imageList == null) {
            this.imageList = new ArrayList<>();
        }
        int size = imageList.size();
        image.setOrd(size);
        this.imageList.add(image);
    }

    public void addImageString(String fileName) {
        ProductImage image = ProductImage.builder()
                .fileName(fileName)
                .build();
        addImage(image);
    }
    
        public void clearList() {
        this.imageList.clear();
    }

서비스로직에서 사용시

    @Override
    public Long modify(ProductRequest request) {
        // 조회
        Product product = productRepository.findById(request.getPno())
                .orElseThrow(() -> new RuntimeException("해당 상품이 없습니다. pno: " + request.getPno()));

        // 변경 내용 반영
        product.changeName(request.getPname());
        product.changePrice(request.getPrice());
        product.changeDesc(request.getPdesc());
        product.changeDelFlag(request.isDelFlag());

        // 이미지 처리
        List<String> uploadedFileName = request.getUploadedFileName();
        // 기존 이미지 삭제
        product.clearList();

        if (!CollectionUtils.isEmpty(uploadedFileName)) {
            uploadedFileName.forEach(product::addImageString);
        }

        // 저장
        Product savedProduct = productRepository.save(product);

        return savedProduct.getPno();
    }
profile
배운 것을 기록합니다.

0개의 댓글