성장하는 개발자의 블로그

[Spring Boot] MyBatis ResultMap 활용하기 본문

Spring Boot

[Spring Boot] MyBatis ResultMap 활용하기

zxzc1297 2024. 7. 16. 20:03
반응형

mybatis 를 사용하여 개발 도중 단순한 select 해서 나온 결과가 json안의 json 형태의 데이터로 나와야하는 경우가 있었다. 단순하게 말하자면 join을 하여 select한 결과가 그룹 1, 그룹 2 등으로 나누어져 반복문을 돌려야 했고, js에서 ajax로 불러왔을 때 반복문을 돌리면서 그룹별로 돌릴 필요가 있었기에 result 자체를 묶어서 보내고 싶었다.

 

즉, java의 자료형으로 쓰자면 List<Map<String, Object>> 의 형태에서 Object 중 하나가 다시 List<Map<String,Object>> 의 형태로 사용하고 싶었다.

 

이를 위해 우선 model을 구성하였다.

import lombok.Data;

import java.util.List;
@Data
public class CustomGroup {
    private int groupSeq;
    private String title;
    private int groupType;
    private int subType;
    private List<GroupItems> items;
}

 

기준이 될 그룹을 이렇게 생성하였고

 

이 모델 안의 리스트에 해당하는 모델은 아래처럼 생성하였다.

import lombok.Data;

@Data
public class GroupItems {
    private String itemSeq;
    private String itemType;
    private String itemName;
}

 

이제 기본적인 model 준비는 끝났다. 이후 Mapper 인터페이스 파일과 xml 파일만 수정하면 끝이난다. 

 

아래는 매퍼파일의 설정이다 부르고자 하는 메소드에 @ResultMap("{xml파일에서 할당한 id 이름}") 만 붙여주면 된다.

import com.test.model.main.CustomGroup;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.ResultMap;

import java.util.List;
import java.util.Map;

@Mapper
public interface GroupMapper {

    @ResultMap("groupItemsResultMap")
    List<CustomGroup> getItemList();
}

 

이후 xml파일에서 id에 맞게 순차적으로 연결을 시켜주면 된다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.test.mapper.main.GroupMapper">

    <resultMap id="itemResultMap" type="com.test.model.main.GroupItems">
        <id property="itemSeq" column="itemSeq"/>
        <result property="itemType" column="itemType"/>
        <result property="itemName" column="itemName"/>
    </resultMap>

    <resultMap id="groupItemsResultMap" type="com.test.model.main.CustomGroup">
        <id property="groupSeq" column="groupSeq"/>
        <result property="title" column="title"/>
        <result property="groupType" column="groupType"/>
        <result property="subType" column="subType"/>
        <collection property="items" ofType="com.test.model.main.CustomItems" resultMap="itemResultMap"/>
    </resultMap>

    <select id="getItemList" statementType="CALLABLE" resultMap="groupItemsResultMap">
        <![CDATA[
		    call UP_ITEM_LIST_R ()
	    ]]>
    </select>


</mapper>

 

mapper.xml 파일을 보면

우선 getItemList 를 호출하여 일반적인 결과를 가져온다.

이후 resultMap으로 "groupItemsResultMap" 을 연결시켜주고 이 resultMap 안의 collection property 에서 itemResultMap을 연결 시켜준다.

 

이 과정을 거치게 되면result property 의 기준으로 데이터가 맞게 들어가게 된다 collection property 에 리스트가 들어가게 된다 

 

예를 들어,

groupSeq title groupType subType itemSeq itemType itemName
1 제목1 1 3 1 A 이름1
1 제목1 1 3 2 B 이름2
2 제목2 2 2 3 C 이름3
2 제목2 2 2 4 D 이름4

 

이런 데이터가 있다면

 

최종적으로

 

[{
    groupSeq : 1,
    title : 제목1,
    groupType : 1,
    subType: 3,
    items : [{
                itemSeq : 1,
                itemType : A,
                itemName : 이름1,
            },
            {
            	itemSeq : 2,
                itemType : B,
                itemName : 이름2,
            }],
},
{
    groupSeq : 2,
    title : 제목2,
    groupType : 2,
    subType: 2,
    items : [{
                itemSeq : 3,
                itemType : C,
                itemName : 이름3,
            },
            {
            	itemSeq : 4,
                itemType : D,
                itemName : 이름4,
            }],
}]

 

이런 형식의 데이터를 받을 수 있게 된다.

 

이런 기능을 사용함에 있어 물론 이 방법 말고 더 좋은 방법이 있을 수 있다. 나는 이미 기존에 짜여진 쿼리를 수정하는 방법을 피해 어떤 방법이 있을까 하고 찾게된 방법이다. 이 글을 읽는 분들은 더 좋은 방법이 있다면 해당 방법을 사용하여 데이터를 가져오면 될 것 같다.