220421 TIL (@MappedCollection)

Minseok-Choi·2022년 4월 21일
0

TIL

목록 보기
3/11

학습자료

https://docs.spring.io/spring-data/jdbc/docs/2.3.1/api/org/springframework/data/relational/core/mapping/MappedCollection.html

@MappedCollection, keyColumn

  • 위 spring 공식문서만 보더라도 내용이 아주 간단하기 때문에, 쉽게 이해할 수 있다.

  • 1:N 관계를 하나의 객체에 맵핑하기위해서 List와 Map 컬렉션을 사용하기 위해서는 _key와 같은 컬럼을 필요로 한다.

  • Map을 활용할때는 key로 활용되고, List를 활용한다면 key를 통해서 순서를 보장한다.

  • 하지만 @MappedCollection을 활용해서 idColumn과 Key컬럼을 지정해준다면 _key와 같은 컬럼을 굳이 만들지 않아도 될 수 있다.

  • 현재 진행중인 미션 프로젝트의 예제로 dish는 여러 이미지를 가지는 1:N 관계이다.

CREATE TABLE image(
                      id      BIGINT PRIMARY KEY AUTO_INCREMENT,
                      name    VARCHAR(500) not null,
                      dish_id BIGINT,
                      foreign key (dish_id) references dish(id)
);
  • keyColumn에 해당하는 dish_key와 같은 컬럼이 필요한데, 순서가 보장될 필요가 없다면, 이미 존재하고 있는 컬럼을 키컬럼으로 지정해주는 것이 좋다. 혹은 IdColumn과 keyColumn을 동일하게 넣어주어도 상관없다.
public class Dish {


    @Id
    private final Long id;
    private final Long categoryId;
    // 순서가 꼭 보장할 필요가 없을 것 같아 id를 keyColumn으로 활용
    // dish의 id가 아닌 image의 id
    @MappedCollection(idColumn = "dish_id", keyColumn = "id")
    private final List<Image> images;
    
    ...
}
public class Image {
    @Id
    private final Long id;
    private final String name;
}
  • findDishById(1L) 메서드에서 image를 찾는 쿼리
  • List에서는 keyColumn의 역할은 단순히 order by이다.
  • Map에서는 Key 역할을 해서 value를 맵핑하니 더 의미가 있을 수 있겠다.
[SELECT "IMAGE"."ID" AS "ID", "IMAGE"."NAME" AS "NAME", "IMAGE"."ID" AS "ID" FROM "IMAGE" WHERE "IMAGE"."DISH_ID" = ? ORDER BY "ID"]
  • 쿼리를 log로 찍어보기전에는 join을 통해서 중복 raw를 찾아서 1에 N를 매핑해주는 로직으로 생각했었다.
  • 하지만 아래와 같이 select쿼리를 두 번 보내는 것을 확인할 수 있었다.
// 일치하는 id의 dish 정보를 가져오는 쿼리
[SELECT "DISH"."ID" AS "ID", "DISH"."NAME" AS "NAME", "DISH"."PRICE" AS "PRICE", "DISH"."STOCK" AS "STOCK", "DISH"."EVENT_ID" AS "EVENT_ID", "DISH"."CATEGORY_ID" AS "CATEGORY_ID", "DISH"."DESCRIPTION" AS "DESCRIPTION", "DISH"."POINT_PERCENT" AS "POINT_PERCENT", "DISH"."DELIVERY_TYPE" AS "DELIVERY_TYPE", "DISH"."DISCOUNT_POLICY" AS "DISCOUNT_POLICY" FROM "DISH" WHERE "DISH"."ID" = ?]
// 일치하는 dish_id의 image를 가져오는 쿼리
[SELECT "IMAGE"."ID" AS "ID", "IMAGE"."NAME" AS "NAME", "IMAGE"."ID" AS "ID" FROM "IMAGE" WHERE "IMAGE"."DISH_ID" = ? ORDER BY "ID"]

1:N을 활용하면 발생하는 [warn] log

2022-04-22 02:23:22.627  WARN 7786 --- [           main] o.s.d.j.core.convert.ResultSetAccessor   : ResultSet contains ID multiple times
2022-04-22 02:23:22.628  WARN 7786 --- [           main] o.s.d.j.core.convert.ResultSetAccessor   : ResultSet contains ID multiple times
2022-04-22 02:23:22.628  WARN 7786 --- [           main] o.s.d.j.core.convert.ResultSetAccessor   : ResultSet contains ID multiple times

TODO

  • 오늘은 1:N을 적용하느라 N:N에 대해서 예제로 실습해보지 못했다.
  • N:N을 꼭 실습해보자.
  • warning로그에 대해서 검색하다가 @Transient 어노테이션을 키워드로 알게 되었다. 요건 또 뭔지 공부해보자.
  • join과 rowMapper 또한 활용해서 더 적절하게 데이터를 뽑을 수 있도록 활용, 연습해봐야겠다.
profile
차곡차곡

0개의 댓글