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 으로 사용하게 되면 리턴값에 해당하는 객체 클래스를 정의할 필요가 없다는게 장점이 되겠네.