์์ ๊ธ๋ ๋ณด์๋ฉด ์ข์์ฉ
ํฌํธํด๋ฆฌ์ค ์ฝ์ง(..)์ค์ด๋ผ ๋ธ๋ก๊ทธ๊ฐ ๋ธํ๋ค
์ค๋ ํ๋ฃจ์ข ์ผ ์ฝ์งํ ๊ฒฐ๊ณผ๋ฅผ ์จ๋ณด๊ฒ ๋ค
๊ฒ์ํ์ ๊ตฌํํ๊ณ ์๋ค.
๊ฒ์๊ธ 1๊ฐ์ ํ์ผ์ ์ต๋ 10๊ฐ๊น์ง ์ ์ฅ๋ ์ ์๋ค.
DB๋ ์๋ ํ๋์ ๋์ผํ๊ฒ ๊ตฌํ๋์ด์๋ค๊ณ ์๊ฐํ์(=postํ ์ด๋ธ๊ณผ postfileํ ์ด๋ธ)
class Post{
Long id;
String title;
String content;
}
class PostFile{
Long postId;
String filePath;
String fileName;
}
@Mapper
@Repository
public interface PostRepository {
@Select("select * from post where id=#{postId}")
Post findById(Long postId);
}
@Mapper
@Repository
public interface PostFileRepository {
@Select("select * from postfile where postid=#{postId}")
List<PostFile> findById(Long postId);
}
๊ฒ์๊ธ ์์ธ๋ณด๊ธฐ๋ฅผ ์ผ๋จ ๋๋๋๋ก ๊ตฌํํด๋ณด์
์ ์ฅ๋ post์ postfile์ ๊ฐ์ ธ์ค๋๋ฐ, postfile์์๋ ์ด๋ฆ๋ง ์์ด๋๋๋๊น ์ด๋ฆ๋ง ๊ฑธ๋ฌ๋ด์ ๋ฐ์ดํฐ๋ฅผ ์๋ตํด์ค๋ค
public Map<String, Object> detail(Long postId) {
Post post = postRepository.findById(postId);
PostDTO.Response postRes = new PostDTO.Response(post);
Map<String, Object> result = new HashMap<>();
result.put("post", postRes);
List<PostFile> postFiles = postFileRepository.findById(postId);
List<String> postFileNames = new ArrayList<>();
for (PostFile postFile : postFiles) {
postFileNames.add(postFile.getFileName());
}
result.put("postFileNames", postFileNames);
return result;
}
์ผ๋จ post๊ฐ์ ๊ฒฝ์ฐ์ ์ํฐํฐ๋ฅผ ์ง์ view๋ก ๋ด๋ ค์ฃผ๊ณ ์๋ค
ํฅํ ํ์ฅ์ฑ์ ๊ณ ๋ คํด์ ์ํฐํฐ๋ฅผ dto๋ก ๋ณํํด์ ๋ด๋ ค์ฃผ์
class PostDTO{
Long id;
String title;
String content;
List<String> fileNames;
}
๊ทธ๋ฆฌ๊ณ ๊ตณ์ด DB์ 2๋ฒ ์ ๊ทผํด์ผํ๋? JOIN์ผ๋ก ํด๊ฒฐํ ์ ์์ง ์์๊น?
SELECT post.id, post.title, post.content, postfile.filename
FROM post LEFT JOIN postfile ON post.id=postfile.postid;
21๋ฒ ๊ฒ์๊ธ ๊ฐ์ ๊ฒฝ์ฐ์ ํ์ผ์ด 6๊ฐ๊ฐ ์๊ธฐ๋๋ฌธ์ 6๋ฒ ์ค๋ณตํด์ ๋์จ๋ค
id, title, content ์ค๋ณต์ ์ด๋ป๊ฒ ํด๊ฒฐํ์ง? ๋ filename์ ๋ฆฌ์คํธ๋ก ๊ฐ์ ธ์ฌ์๋์์๊น???
๊ฒ์ํด๋ณด๋ ์๋์ ๊ฐ์ด ๋์จ๋ค
//Xml
//์คํ : findPostAndFileById(Long postId);
<resultMap id="postAndFileMap" type="PostDTO">
<id property="id" column="id"></id>
<result property="title" column="title"></result>
<result property="content" column="content"></result>
<collection property="fileNames" column="filename" javaType="List" ofType="String" select="findFileById"></collection>
</resultMap>
<select id="findPostAndFileById" resultMap="postAndFileMap" parameterType="Long">
select * from post where id=#{postId}
</select>
<select id="findFileById" resultType="String" parameterType="Long">
select filename from postfile where postid=#{postId}
</select>
//์ด๋
ธํ
์ด์
//์คํ : findPostAndFileById(Long postId);
@Select("select * from post where id=#{postId}")
@Results(
id="id", value = {
@Result(property="title", column="title"),
@Result(property="content", column="content"),
@Result(property = "fileNames", javaType = List.class, many=@Many(select="findFileById"))
})
PostDTO findPostAndFileById(Long postId);
@Select("select filename from postfile where postid=#{postId}")
List<String> fileNames = findFileById(Long postId);
xml์ <id>, ์ด๋ ธํ ์ด์ ์ id๋ฅผ ์ฌ์ฉํ๋ฉด post์ฒ๋ผ ์ค๋ณต๋๋ ๊ฒฐ๊ณผ๋ ์ ์ธํด์ ์ฑ๋ฅ์ ํฅ์์ํจ๋ค๊ณ ํ๋ค
์ฌ๊ธฐ์ ๋จ์ ์ <collection>๊ณผ @Many์์ select๋ฌธ์ ์ฌ์ฉํ๋ฉด N+1๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค๋ ๊ฒ!!
findPostAndFileById()๋ฅผ ์คํํ๋ฉด ์๋์ผ๋ก findFileById()๊ฐ ์คํ๋๊ณ , List ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค์ด๋ธ๋ค.
๋ค์๋งํด,
findPostAndFileById()๋ฅผ ์คํํ๊ณ (DB์ ์์ฒญ 1๋ฒ)
๋ฆฌ์คํธ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค๊ธฐ์ํด ํ์ผ์ด ์๋๋งํผ findFileById()๋ฅผ ์คํํ๋ค(ํ์ผ์ด 6๊ฐ๋๊น DB์ ์์ฒญ 6๋ฒ..)
๊ทธ๋ฌ๋ฉด ์ด๋ป๊ฒ ํด์ผํ๋..
Nested ResultMap์ ์ฌ์ฉํ๋ฉด ๋๋ค๊ณ ํ๋ค
//Xml
//์คํ : findPostAndFileById(Long postId);
//๋๋ List<String> ์ด๋ผ์ ResultMap์ ํ๋ฒ์ ๋ชฐ์์ฃผ๊ฒ ๋ค
<resultMap id="postAndFileMap" type="PostDTO">
<id property="id" column="id"></id>
<result property="title" column="title"></result>
<result property="content" column="content"></result>
<collection property="fileNames" column="id" select="fileMap"></collection>
</resultMap>
<resultMap id="fileMap" type="String">
<result column="filename"></result> //property๊ฐ ์๋ ์ด์ ๋ List<String>์ด๋ผ ํ๋๊ฐ ์์ด์
</resultMap>
<select id="findPostAndFileById" resultMap="postAndFileMap" parameterType="Long">
select post.*, postfile.filename
from post left join postfile on post.id=postfile.postid
where post.id=#{postId}
</select>
์์ฝ๊ฒ๋ <collection>์ ๋์๋๋ ์ด๋ ธํ ์ด์ ์ด @Many๋ผ์.. XML๋ก๋ง ์ฌ์ฉํด์ผ๋ ๊ฒ ๊ฐ๋ค
์ ๊ทผ๋ฐ ์ฌ๊ธฐ์ ๋ํ๋ ๋ฌธ์
PostDTO๋ ์ด๋ ๊ฒ ์๊ฒผ์๋ค. ๊ทธ๋์ resultMap์ ํ๋ํ๋ ํ๋๋ช ์ ์ด๊ฐ๋ฉด์ ๋ง์ถฐ์ฃผ๊ณ ...
class PostDTO{
Long id;
String title;
String content;
List<String> fileNames;
}
๋ง์ฝ PostDTO๊ฐ... ๊ฐ์ฒด๋ ๋ฐ๊ฒ๋๋ค๋ฉด?!
class PostDTO{
Post post;
List<String> fileNames;
}
(๋ญ๊ฐ ORM์ค๋ฝ๊ฒ ๋ณํด๊ฐ๊ณ ์๋ค)
<resultMap id="postMap" type="Post">
<id property="id" column="id"></id>
<result property="title" column="title"></result>
<result property="content" column="content"></result>
</resultMap>
<resultMap id="fileMap" type="String">
<result column="filename"></result>
</resultMap>
<resultMap id="postAndFileById" type="PostDTO">
<association property="post" column="id" select="postMap"></association>
<collection property="fileNames" column="id" select="fileMap"></collection>
//column์ ๋๋ค id์ด๋ค findPostAndFileById์์์ id๋ก ๋งตํํ๋ค
</resultMap>
<select id="findPostAndFileById" resultMap="postAndFileById" parameterType="Long">
select post.*, postfile.filename
from post left join postfile on post.id=postfile.postid
where post.id=#{postId}
</select>
association์ผ๋ก ๋ฐ์์ค๋ฉด๋๋ค!
resultMap์ผ๋ก ํ๋ ํ๋ํ๋ ์ถ๊ฐํด์ฃผ๋๊ฑด ์ด์ฉ์์๋ ๊ฒ ๊ฐ๋ค
association์ has one ๊ด๊ณ๋ก ๊ฐ์ฒด๋ฅผ ๋ฐ์ ๋,
collection์ has many ๊ด๊ณ๋ก ์ปฌ๋ ์ ์ ๋ฐ์ ๋ ์ฌ์ฉํ์