ResultMap에 대한 자세한 정보는 아래 링크에서 확인할 수 있다.
보통의 경우, SELECT 결과값은 자바빈이나 POJO, HashMap, 단일 값이라면 String 등으로 resultType을 결정한다.
만약 컬럼명과 프로퍼티명이 다를 경우, 데이터베이스 별칭을 사용하는 것과 다른 방법으로 명시적인 resultMap 을 선언하는 방법이 있다.
다음을 보면 :
1 2 3 4 5 | < select id = "selectUsers" parameterType = "int" resultMap = "userResultMap" > select user_id, user_name, hashed_password from some_table where id = #{id} </ select > |
여기서 selectUsers는 다음의 userResultMap을 참조하고 있다.
1 2 3 4 5 | < resultMap id = "userResultMap" type = "com.someapp.model.User" > < id property = "id" column = "user_id" /> < result property = "username" column = "username" /> < result property = "password" column = "password" /> </ resultMap > |
column 속성은 데이터베이스 컬럼, property는 자바빈이나 Map타입의 키값을 표현한다.
사실 resultMap을 단순히 컬럼명과 프로퍼티명이 일치하지 않을때 보다는1 좀 더 복잡한 결과를 받아와야 할 때 사용한다.
problem
그 복잡한 결과란 무엇이냐?
예를 들어 다음 그림처럼 BBS 테이블과 그것을 참조하는 Attach 테이블이 있다고 가정하자.
(매우 간결하면서 파일첨부가 가능한 게시판의 테이블 관계도)
그리고 인터페이스 상 특정 글을 보려고 할 때의 쿼리는 다음과 같다고 하자.
1 2 3 4 5 6 7 8 | < select id = "selectBbsDetail" parameterType = "java.lang.Integer" resultType = "com.model.Bbs" > SELECT b.bbs_id, b.name, b.title, b.content, b.regdate, a.attach_id, a.file_name, a.file_size FROM bbs b LEFT JOIN attach a ON b.bbs_id = a.bbs_id WHERE b.bbs_id = #{id} </ select > |
각 게시글에 단 하나의 첨부파일만 존재한다면 문제가 발생하지 않는다. 하지만, 두 테이블의 관계는 1:N 의 관계이므로 하나의 글에 여러 첨부파일이 존재할 수 있다. 그리고 그 경우라면 분명 예외가 발생할 것이다.
bbs_id | name | title | content | regdate | attach_id | file_name | file_size
---------------------------------------------------------------------------------------------------------------------------
1003 me 제목 내용내용.. 오늘 24 1e2435.jpg 2349890
1003 me 제목 내용내용.. 오늘 25 4e981A.jpg 5799101
1003 me 제목 내용내용.. 오늘 25 weeeee.jpg 100382901
// org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException
solution
위 문제는 data concatenating2(참고) 등의 방법으로 해결할 수 있으나 여기선 resultMap을 사용해보겠다.
우선 다음 코드로 출발한다 :
1 2 3 4 5 6 7 8 | < select id = "selectBbsDetail" parameterType = "java.lang.Integer" resultMap = "bbsResultMap" > SELECT b.bbs_id, b.name, b.title, b.content, b.regdate, a.attach_id, a.file_name, a.file_size FROM bbs b LEFT JOIN attach a ON b.bbs_id = a.bbs_id WHERE b.bbs_id = #{id} </ select > |
참조하고 있는 bbsResultMap은 :
1 2 3 4 5 6 7 | < resultMap id = "bbsResultMap" type = "java.util.HashMap" > < id property = "bbs_id" column = "bbs_id" /> < result property = "name" column = "name" /> < result property = "title" column = "title" /> < result property = "content" column = "content" /> < collection property = "attachList" javaType = "java.util.ArrayList" resultMap = "bbsAttachResultMap" /> </ resultMap > |
type을 자바빈이 아닌 HashMap으로 받는것 외엔 차이가 없다. 그러나 위처럼 resultMap으로 매핑할 경우 단순히 컬럼명과 프로퍼티명의 불일치만 해결해주는 것이 아니라 중복되는 결과를 받았을 때 이를 자동으로 걸러내주는 효과도 있다. 이는 하위 요소인 <id>를 사용했기 때문이다.
그리고 <collection>은 child rows3를 처리하는 방법을 나타낸다. 여기서는 bbsAttachResultMap을 참조하고 있고 이는 다음과 같다:
1 2 3 4 5 | < resultMap id = "bbsAttachResultMap" type = "java.util.HashMap" > < id property = "attach_id" column = "attach_id" /> < result property = "file_name" column = "file_name" /> < result property = "file_size" column = "file_size" /> </ resultMap > |
이제 마이바티스는 다음과 같은 MAP타입의 값을 리턴할 것이다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | { content=내용내용.., title=제목, bbs_id=1003, regdate=오늘, name=me, attachList=[ { file_size=2349890, attach_id=24, file_name=1e2435.jpg }, { file_size=5799101, attach_id=24, file_name=4e981A.jpg }, { file_size=100382901, attach_id=24, file_name=weeeee.jpg } ] } |
이 값을 만약 자바로 하드코딩 한다면 다음과 같다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | HashMap<String, Object> rows = new HashMap<String, Object>(); rows.put( "bbs_id" , "1003" ); rows.put( "name" , "me" ); rows.put( "title" , "제목" ); rows.put( "content" , "내용내용.." ); rows.put( "regdate" , "오늘" ); ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>(); HashMap<String, String> childRows = new HashMap<String, String>(); childRows.put( "attach_id" , "24" ); childRows.put( "file_name" , "1e2435.jpg" ); childRows.put( "file_size" , "2349890" ); list.add(childRows); childRows.clear(); childRows.put( "attach_id" , "24" ); childRows.put( "file_name" , "4e981A.jpg" ); childRows.put( "file_size" , "5799101" ); list.add(childRows); childRows.clear(); childRows.put( "attach_id" , "24" ); childRows.put( "file_name" , "weeeee.jpg" ); childRows.put( "file_size" , "100382901" ); list.add(childRows); rows.put( "attachList" , list); |