DevBoi

[JPA] ElementCollection 본문

Develop/[JPA]

[JPA] ElementCollection

HiSmith 2023. 8. 28. 00:11
반응형

Entity 에서 properties로 아래와 같이 저장하고싶을때가 있다.

 

List<String> tags

 

이를 해결하고 JPA는 어떻게 관리하는 지 알아보자

우선 내가 사용하는 Entity 타입이다.

package com.boiler.flutterbackend.app.group.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.time.LocalDateTime;
import java.util.List;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class GroupResDto {
  private Long group_no;

  private String userId;

  private String place;

  private String title;

  private String content;
  @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
  private LocalDateTime date;

  private String gender;

  private int memberCnt;

  private List<String> region;

  private List<String> introduce_tag;
  private String nickname;
  private String thumbnailImageUrl;
}

 

기본 골격은 Entity, Dto같다고 생각해보자

문제는 저 region값이 List<String>, List<CustomDomain> 인 경우이다.

이럴떄는 어떻게 해야할까?

 

우선 해당 properties로 Entity를 생성하면, 이렇게 된다

package com.boiler.flutterbackend.app.group.entity;

import com.boiler.flutterbackend.app.entity.BaseEntity;
import com.boiler.flutterbackend.app.group.dto.GroupReqDto;
import com.boiler.flutterbackend.app.user.entity.User;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.time.LocalDateTime;
import java.util.List;

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "Groups")
public class Group extends BaseEntity {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  Long group_no;
  @Column
  String title;
  @Column
  String content;
  @Column
  LocalDateTime date;
  @Column
  String gender;
  @Column
  int memberCnt;
  @Column
  String place;
  @ElementCollection(fetch = FetchType.LAZY)
  @Column
  List<String> region;
  @ElementCollection(fetch = FetchType.LAZY)
  @Column
  List<String> introduce_tag;
  @ManyToOne
  @JoinColumn(name = "id")
  private User user;

  public Group(GroupReqDto dto){
    this.title=dto.getTitle();
    this.content=dto.getContent();
    this.date=dto.getDate();
    this.region=dto.getRegion();
    this.introduce_tag=dto.getIntroduce_tag();
    this.memberCnt=dto.getMemberCnt();
    this.gender = dto.getGender();
    this.place = dto.getPlace();
  }
}

 

위와 같이 연관 테이블들이 Generate된다.

이말은 뭐냐면, 관련 된 태그들이 Group id 를 연관지어서 별도의 테이블이 생성된다는 의미이다.

근데 Querydsl에서는 QEntity로 접근하는데, Entity는 별도로 관리하지 않는데...그럼 어떻게 조회할까 라고 생각을 한다.

그래서 여러가지 방법이 있지만

나는 Projection constructor를 사용하여, transform을 추천한다.

 

 

관련 소스는 아래와 같다.

@Override
  public List<?> getGroupList(String userId) {
    return queryFactory
      .selectFrom(group)
      .leftJoin(user).on(group.user.userId.eq(user.userId))
      .transform(groupBy(group.group_no).list(
        Projections.constructor(GroupResDto.class,
          group.group_no,
          user.userId,
          group.place,
        group.title,
        group.content,
        group.date,
          group.gender,
          group.memberCnt,
        list(group.region),
          list(group.introduce_tag),
            user.nickname,
            user.thumbnailImageUrl
          ))).stream().toList();
  }

 

List<String> 인경우 + 통상적으로 Response엔티티를 별도로 사용하기 때문에 region과 introduce_tag의 경우, list()로 감싸고

해당 Projections을 생성해서 매핑한다.

 

보기 쉽게 개행을 해줬다.

 

이렇게 되면, 해당 GroupResDto에 List<String> 타입에 regison과 태그가 매핑이 되어서 잘 저장된다.

 

 

추가로, 자동으로생성되는 부가 테이블의 데이터는 아래와 같은 구조로 자동 생성된다.

 

transform groupby를 사용한다는 점, 그리고 Projection.construtor를 사용한다는 점을 보면 좋을 것 같다.

반응형

'Develop > [JPA]' 카테고리의 다른 글

[JPA] JPAUpdateClause 사용  (0) 2023.09.02
[Jpa] Querydsl build Setting  (0) 2023.09.02
[JPA] QueryDsl LeftJoin,SelfJoin  (0) 2023.08.19
[JPA] QueryDsl 여러 기능 정리  (0) 2023.08.19
[JPA] 친구 관련 API개발  (0) 2023.08.19