본문 바로가기

SpringBoot

[연재] SpringBoot diary - mybatis resultType="map"

728x90
반응형

원문은 https://blog.woohahaapps.com/mybatis-resulttypemap/ 에서 확인할 수 있습니다.

spring boot 학습으로 study.diary 프로젝트를 만들어 봤었는데 mybatis 를 통해서 일기 내용을 가져오는 GetDiary 의 resultType 으로 domain 클래스를 지정했었지.

<mapper namespace="com.woohahaapps.study.diary.mapper.DiaryMapper">
    ...
    <select id="GetDiary" resultType="com.woohahaapps.study.diary.domain.Diary">
        select 
            *
        from diary
        where id=#{id};
    </select>
</mapper>

이렇게 설정하면 GetDiary 쿼리의 결과로 얻어지는건 Diary 클래스 객체가 되지.

@Data
public class Diary {
    private Integer id;
    private LocalDate diary_date;
    private String diary_content;
}

이번에는 resultType 으로 map 을 지정해서 key-value 형식의 데이터를 가져오는 방법으로 수정해보려고 해.

일단 쿼리문을 정의한 매퍼 xml 파일(DiaryMapper.xml)에서 resultType 을 map 으로 바꿔볼께. map 대신 hashmap 을 사용해도 큰 차이가 없어.

DiaryMapper.xml
<mapper namespace="com.woohahaapps.study.diary.mapper.DiaryMapper">
    ...
    <select id="GetDiary" resultType="map">
        select 
            *
        from diary
        where id=#{id};
    </select>
</mapper>

이렇게 변경하고나면 매퍼 인터페이스(DiaryMapper.java)의 GetDiary 함수의 리턴값을 map 의 형식에 맞는 데이터형으로 변경해 주어야 해.

DiaryMapper.java
@Mapper
public interface DiaryMapper {
    ...
    public Diary GetDiary(Integer id);
    public Map<String, Object> GetDiary(Integer id);
    ...
}

리턴값 데이터형이 변경되었기 때문에 Service, Controller 에도 줄줄이 변경을 해줘야겠지.

DiaryService.java
@Service
public class DiaryService {
    ...
    public Diary GetDiary(Integer id) {
    public Map<String, Object> GetDiary(Integer id) {
        return diaryMapper.GetDiary(id);
    }
    ...
}
DiaryController.java
@RestController
public class DiaryController {
    ...
    // Read
    @GetMapping("/diary/{id}")
    public Diary GetDiary(@PathVariable("id") Integer id) {
    public Map<String, Object> GetDiary(@PathVariable("id") Integer id) {
        return diaryService.GetDiary(id);
    }
    ...
}
DiaryUIController.java
@Controller
public class DiaryUIController {
   ...
    // Edit
    @GetMapping("/diary/edit/{id}")
    public String EditDiary(@PathVariable("id") Integer id, Model model) {
        Diary diary = diaryService.GetDiary(id);
        Map<String, Object> diary = diaryService.GetDiary(id);
        model.addAttribute("diary", diary);

        return "diary/editdiary";
    }
}

마지막으로 diary/editdiary.html 파일에서 타임리프가 데이터를 처리하는 방법의 코드도 변경해야 해.

<form th:action="@{/diary}" th:method="post">
    <input type="hidden" name="_method" value="PUT" />
    <input type="hidden" id="id" name="id" th:value="${diary.id}" />
    <input type="hidden" id="id" name="id" th:value="${diary['id']}" />
    <label for="diary_date">날짜:</label>
    <input type="text" id="diary_date" name="diary_date" th:value="${#temporals.format(diary.diary_date, 'yyyy-MM-dd')}" />
    <input type="text" id="diary_date" name="diary_date" th:value="${diary['diary_date']}" />
    <label for="diary_content">내용:</label>
    <textarea rows="10" id="diary_content" name="diary_content" th:value="${diary.diary_content}" th:text="${diary.diary_content}"></textarea>
    <textarea rows="10" id="diary_content" name="diary_content" th:value="${diary['diary_content']}" th:text="${diary['diary_content']}"></textarea>
    <input type="submit" value="저장(수정)" />
</form>
</body>

. 으로 객체의 멤버에 접근하는 방식이 아니라, key – value 방식으로 접근하기 위해서 [ ] 괄호 안에 key 값을 적어주어야 하는거지. 그리고 diary_date 키의 값은 문자열형이기 때문에 temporals.format 함수로 더이상 변환할 필요가 없어졌어.

GetDiary 함수에 대한 리턴값(http://localhost:8080/diary/1)은 아래와 같이 표현이 돼.

일기내용을 읽어서 html 파일로 표현하는 결과(http://localhost:8080/diary/edit/1)도 동일해지지.

resultType 을 객체클래스의 패키지명으로 사용하는 대신 map 으로 사용하게 되면 리턴값에 해당하는 객체 클래스를 정의할 필요가 없다는게 장점이 되겠네.

반응형