현재 사내 프로젝트에서 게시물 API를 구현하고 있다.
게시물을 등록할 때, 여러 개의 첨부파일을 등록할 수 있도록 했다.
이처럼, 그 게시물의 상세정보를 불러올 때 1:N 관계의 데이터를 어떻게 하면 효율적으로 가져올 수 있을지 고민이었다.
찾아보니 이러한 1:N 관계의 데이터를 마이바티스에서 제공하는 <resultMap>과 <collection>을 활용하면
한 번의 쿼리로 1:N 관계의 데이터를 객체 형태로 가져올 수 있었다.
우선 게시물과 첨부파일 테이블 구조를 알아보자.
게시물 정보 테이블 (BBS_INFO)
컬럼명 (Field) | 데이터 타입 (Type) | 제약 사항 | 설명 (Comment) |
SQ | int(11) | PK, auto_increment | 시퀀스 |
BBS_TYPE | char(1) | default ‘N’ | 게시글타입 (N,F) |
TITLE | varchar(100) | - | 제목 |
CONTENTS | text | - | 내용 |
V_ADMIN | smallint(6) | default 0 | 관리자보기 권한 |
V_LEADER | smallint(6) | default 0 | 팀장보기권한 |
V_EMP | smallint(6) | deafult 0 | 직원보기권한 |
REG_EMP_ID | varchar(20) | - | 신청자ID |
USE_YN | char(1) | deafult ‘Y’ | 사용유무 |
REG_DT | datetime | default current_timestamp | 등록일 |
UPD_DT | datetime | on update current_timestamp() | 수정일 |
파일정보 테이블 (BBS_FILE)
컬럼명 (Field) | 데이터 타입 (Type) | 제약 사항 | 설명 (Comment) |
SQ | int(11) | PK / auto_increment | 시퀀스 |
BBS_SQ | int(11) | FK | 게시물 SQ |
FILE_NAME | varchar(100) | - | 파일명 |
FILE_PATH | varchar(100) | - | 파일경로 |
파일정보 테이블을 보면 외래키로 게시물정보 SQ 를 갖고 있다.
이어서 DTO 구조를 살펴보자. 아래와 같이 구성했다.
게시물 정보 DTO (BbsDTO)
@Data
@EqualsAndHashCode(callSuper=false)
@Alias("bbsDTO")
@Schema(description = "공지사항 및 자료실 DTO")
public class BbsDTO extends SearchDTO {
@Schema(description = "게시글 ID(시퀀스)", example = "1")
public int _seq;
@Schema(description = "게시글 타입", example = "N/F(Notice/File)")
public String bbs_type;
@Schema(description = "게시글 제목")
public String title;
@Schema(description = "게시글 내용")
public String contents;
@Schema(description = "작성자 ID")
public String emp_id;
@Schema(description = "작성자명")
public String emp_name;
@Schema(description = "관리자 보기 권한", example = "0 or 1")
public int view_admin;
@Schema(description = "팀장 보기 권한", example = "0 or 1")
public int view_leader;
@Schema(description = "직원 보기 권한", example = "0 or 1")
public int view_emp;
@Schema(description = "첨부 파일 정보")
public List<FileDTO> fileList;
@Schema(description = "사용유무", example = "Y/N")
public String use_yn;
@Schema(description = "등록일")
public String reg_date;
@Schema(description = "수정일")
public String upd_date;
}
파일 정보 DTO (FileDTO)
@Data
@Alias("fileDTO")
@Schema(description = "파일 DTO")
public class FileDTO {
@Schema(description = "파일 시퀀스(ID)")
private int file_seq;
@Schema(description = "게시글 ID")
private int bbs_seq;
@Schema(description = "파일명")
private String file_name;
@Schema(description = "파일 경로")
private String file_path;
}
BbsDTO를 보면서 파일정보를 List형태로 받기위해 List<FileDTO> 구성했다.
이제 resultMap과 collection에 대해서 알아보자.
resultMap
SQL 쿼리 결과를 자바 객체(DTO 등)에 어떻게 매핑할지 상세하게 정의하는 설계도 같은거다.
컬럼명과 객체 필드명이 다른 경우 또는 이와 같이 1:N 관계 데이터를 가져와야 하는 경우 사용한다.
collection
<resultMap> 안에서 1:N 관계의 'N' 에 해당하는 부분을 처리하는 특별 지침
List와 같은 컬렉션 객체로 묶어주는 역할
데이터베이스에서는 여러 줄로 조회된 결과를 자바에서는 List를 포함한 단일 객체로 깔끔하게 받을 수 있다.
작성한 쿼리를 보자.
<!-- 게시물 상세정보 쿼리 -->
<select id="getBbsInfoDetail" parameterType="bbsDTO" resultMap="bbsDetailResultMap">
SELECT
bbs.SQ AS bbs_sq,
bbs.BBS_TYPE AS bbs_type,
bbs.TITLE AS title,
bbs.CONTENTS AS contents,
bbs.REG_EMP_ID AS emp_id,
emp.EMP_NAME AS emp_name,
bbs.USE_YN AS use_yn,
bbs.REG_DT AS reg_date,
bbs.UPD_DT AS upd_date,
file.SQ AS file_seq,
file.FILE_NAME AS file_name,
file.FILE_PATH AS file_path
FROM
BBS_INFO bbs
LEFT JOIN EMP_INFO emp ON bbs.REG_EMP_ID = emp.EMP_ID
LEFT JOIN BBS_FILE file ON bbs.SQ = file.BBS_SQ
<where>
bbs.SQ = #{_seq}
<if test="use_yn != null and use_yn != ''">
AND bbs.USE_YN = #{use_yn}
</if>
</where>
</select>
<resultMap id="bbsDetailResultMap" type="bbsDTO">
<id property="_seq" column="bbs_sq"/>
<result property="bbs_type" column="bbs_type"/>
<result property="title" column="title"/>
<result property="contents" column="contents"/>
<result property="emp_id" column="emp_id"/>
<result property="emp_name" column="emp_name"/>
<result property="use_yn" column="use_yn"/>
<result property="reg_date" column="reg_date"/>
<result property="upd_date" column="upd_date"/>
<collection property="fileList" ofType="FileDTO">
<id property="file_seq" column="file_seq"/>
<result property="bbs_seq" column="bbs_sq"/>
<result property="file_name" column="file_name"/>
<result property="file_path" column="file_path"/>
</collection>
</resultMap>
게시물 상세정보 쿼리에서 resultType이 아닌 resultMap으로 설정한다.
resultMap에서 매핑 규칙을 작성하는데, 'N'에 해당되는 파일 정보는 collection으로 구성한다.
이렇게 resultMap과 collection을 활용해 1:N 관계의 데이터를 한 번의 쿼리로 깔끔하게 처리할 수 있다.
'Spring > Java' 카테고리의 다른 글
[Spring] ExceptionHandler를 활용한 자동 예외 처리 (w.RestControllerAdivce) (0) | 2025.07.15 |
---|---|
[Spring][MyBatis] PageHelper로 페이징 처리하기 (4) | 2025.07.11 |
[Spring][JAVA] Spring에서 주중(월~금)만 스케줄러 실행하기 (0) | 2025.04.14 |