๐งท Spring + MyBatis์์ ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ์ ๊ฐ์ฒด๊ฐ ๋งคํ์ด ๋๋ ๊ณผ์
์คํ๋ง์์ ๋ง์ด๋ฐํฐ์ค๋ฅผ ์ฌ์ฉํ ๋, Select ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ์ ๊ฐ์ฒด(Dto)๊ฐ ์ด๋ ํ ์์ ์ ํตํด ๋งคํ์ด ๋๋์ง ์ ํํ๊ฒ ํ์ ํ๊ณ ๊ณต์ ํ๊ธฐ ์ํด ๋งคํ ๊ณผ์ ์ ๋ํด ์ ๋ฆฌํด ๋ณด์์ต๋๋ค.
(๋น์ฐํ ํ๋ฆฐ ๋ด์ฉ์ด ์กด์ฌํ ์ ์์ผ๋ ํผ๋๋ฐฑ ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. ๐)
๐ ๊ฐ์
- Spring๊ณผ MyBatis์์ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์ ๊ฐ์ฒด์ ๋งคํ์ด ์ด๋ฃจ์ด์ง๋ ๊ณผ์ ์ ๋ํด ์ดํด๋ด ๋๋ค.
- ์ด์ ๊ด๋ จํ์ฌ ์ด๋ ํ ๋ฐฉ์์ผ๋ก ๋งคํ์ ์งํํ๋์ง, ์ข์ ๋ฐฉ๋ฒ์ด ๋ฌด์์ธ์ง ๋ฑ์ ๋ํด ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๐ ๊ฒฐ๋ก
ํฌ์คํ ์ด ๊ฝค๋ ์ฅ๋ฌธ์ด๊ธฐ์,, ๋งคํ ๊ณผ์ ์ ๋ํด ๊ฒฐ๋ก ๋ถํฐ ๋ง์๋๋ฆฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ๊ธฐ๋ณธ ์์ฑ์(NoArgs)๋ง ์กด์ฌํ ๊ฒฝ์ฐ, ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์ ๊ฐ์ฒด์ ๋งคํ์ด ์ ์์ ์ผ๋ก ์งํ๋์ง ์์ต๋๋ค. ์ ํํ๊ฒ๋ null๋ก ๋งคํ์ด ๋ฉ๋๋ค.
- ๊ธฐ๋ณธ ์์ฑ์(NoArgs)์ ์ปฌ๋ผ ๋ณ์นญ(Alias)๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ ๋งคํ์ด ์ ์์ ์ผ๋ก ๋ฉ๋๋ค.
- ๋ชจ๋ ํ๋์ ๋ํ ์์ฑ์(AllArgs)๊ฐ ์กด์ฌํ๋ฉด ๋ณ์นญ์ด ์๋๋ผ๋ ๋งคํ์ด ์ ์์ ์ผ๋ก ๋ฉ๋๋ค.
- ๋จ, ๊ฐ์ฒด์ ํ๋์ ์ปฌ๋ผ์ ๋ฐ์ดํฐ ์์๊ฐ ์ผ์นํด์ผ ํฉ๋๋ค.
- ๊ธฐ๋ณธ ์์ฑ์์ ๋ชจ๋ ํ๋์ ๋ํ ์์ฑ์๊ฐ ์๋, ์ผ๋ถ ํ๋์ ๋ํ ์์ฑ์๋ง ์กด์ฌํ ๊ฒฝ์ฐ, ํด๋น ํ๋์ ๋ํด์๋ง ๋ฐ์ดํฐ ๋งคํ์ด ์งํ๋ฉ๋๋ค.
- No Args, All Args๊ฐ ์๋ ์ฌ๋ฌ ๊ฐ์ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ, ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค
- ๋ฆฌํ๋ ์ ์ผ๋ก ์ธํด ๊ฐ์ฒด ํด๋์ค์ getter/setter๋ ํ์ํ์ง ์์ต๋๋ค.
๐ ์์ ์ฝ๋
ํ ์คํธ๋ฅผ ์ํด Dto, Mapper, xml ๋ฑ์ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
(ํ ์คํธ๋ฅผ ์ํด ์ฌ์ฉํ์๊ธฐ์ ํ ์ด๋ธ๋ช ์ด ๋ ์ปฌ๋ผ, ํ๋๋ช ๋ฑ์ ์์๋ก ์ ํ์ต๋๋ค ^^;)
TestDto ๊ฐ์ฒด
1 2 3 4 5 6 7 8 9 10 11 | public class TestDto { private String id; private Long promotionId; private Long itemId; private String type; private String expiredStartDate; private String expiredEndDate; private String useYn; } | cs |
Mapper ์ธํฐํ์ด์ค
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Alias๊ฐ ์ค์ ๋ Mapper @Mapper public interface AliasMapper { List<TestDto> findAll(); } // Alias๊ฐ ์ค์ ๋์ง ์์ Mapper @Mapper public interface NoAliasMapper { List<TestDto> findAll(); } | cs |
Mapper.xml
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 29 30 31 32 33 34 35 36 37 38 39 40 | -- NoAliasMapper.xml <?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.example.mybatisbinding.mapper.NoAliasMapper" > <select id="findAll" resultType="TestDto"> SELECT MC_ID , P_ID , ITEM_ID , MC_FG , YH_S_YMD , YH_E_YMD , USE_YN FROM TEST_TABLE WHERE MC_ID IN ('5716', '5717') -- 2๊ฑด์ ๋ฐ์ดํฐ ์กด์ฌ </select> </mapper> -- AliasMapper.xml <?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.example.mybatisbinding.mapper.AliasMapper" > <select id="findAll" resultType="TestDto"> SELECT MC_ID AS id , P_ID AS promotionId , ITEM_ID AS itemId , MC_FG AS type , YH_E_YMD AS expiredEndDate , YH_S_YMD AS expiredStartDate , USE_YN AS useYn FROM TEST_TABLE WHERE MC_ID IN ('5716', '5717') -- 2๊ฑด์ ๋ฐ์ดํฐ ์กด์ฌ </select> </mapper> | cs |
- AliasMapper.xml ์ ๊ฒฝ์ฐ TestDto ๊ฐ์ฒด์ ํ๋๋ช ๊ณผ ๋์ผํ๊ฒ alias ์ค์ ์ ํฉ๋๋ค.
- xml ํ์ผ์ resultType์์ ํจํค์ง ๊ฒฝ๋ก๋ฅผ ์ ์ธํ ํด๋์ค๋ช ๋ง ์์ฑํ ๊ฒ์ properties(yml) ํ์ผ์ ์๋ ์ค์ ์ ํตํด dto ํ์ผ์ด ์กด์ฌํ๋ ํจํค์ง ๊ฒฝ๋ก๋ฅผ ๋ช ์์ ์ผ๋ก ์ ์ธํ๋ฉด ๋ฉ๋๋ค.
mybatis.type-aliases-package: com.example.mybatisbinding.dto
๐ ํ ์คํธ
์์ฑ์ ๋ฐ alias์ ์ฌ๋ฌ ๊ฐ์ง ์กฐํฉ์ ํตํด ํ ์คํธํด ๋ณด๊ฒ ์ต๋๋ค.
(๋ฐ์์ ์์ธํ ์ค๋ช ๋๋ฆฌ๊ฒ ์ง๋ง, TestDto ๊ฐ์ฒด์์ getter/setter๋ ๋ฐ๋ก ํ์ํ์ง ์์ต๋๋ค.)
- ๊ธฐ๋ณธ ์์ฑ์(@NoArgsConstructor)
- ๊ธฐ๋ณธ ์์ฑ์(@NoArgsConstructor) + ๋ณ์นญ(Alias)
- ๋ชจ๋ ํ๋๋ฅผ ํฌํจํ๋ ์์ฑ์(@AllArgsConstructor)
- ๊ธฐ๋ณธ ์์ฑ์ + ๋ชจ๋ ํ๋๋ฅผ ํฌํจํ๋ ์์ฑ์(@NoArgs + @AllArgs)
- ์ฌ๋ฌ ๊ฐ์ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ
- ์ผ๋ถ ํ๋๋ฅผ ๊ฐ์ง๋ ๋จ ํ๋์ ์์ฑ์๋ง ์กด์ฌํ ๊ฒฝ์ฐ
ํธ์๋ฅผ ์ํด ๊ธฐ๋ณธ ์์ฑ์๋ @NoArgs๋ก, ๋ชจ๋ ํ๋๋ฅผ ํฌํจํ๋ ์์ฑ์๋ @AllArgs๋ก, ๋ณ์นญ์ Alias๋ก ํ๊ธฐํ๊ฒ ์ต๋๋ค.
1. ๊ธฐ๋ณธ ์์ฑ์(@NoArgs)
- ๊ฐ์ฒด(TestDto)์ @NoArgs๋ง ์กด์ฌํ ๊ฒฝ์ฐ, ๊ฐ์ฒด์ ๋งคํ์ด ์ ์์ ์ผ๋ก ์ด๋ฃจ์ด์ง์ง ์์ต๋๋ค.
- ์ข ๋ ์ ํํ๊ฒ๋ ๋ฐ์ดํฐ๊ฐ null๋ก ๋งคํ์ด ๋ฉ๋๋ค.
- ์๋ฅผ ๋ค์ด, ์กฐํ ๊ฒฐ๊ณผ๊ฐ 10๊ฑด์ธ ๊ฒฝ์ฐ, 10๊ฐ์ ๊ฐ์ฒด์ ๋ํ ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ null๋ก ๋งคํ๋ฉ๋๋ค.
- Java์ ๊ฒฝ์ฐ, ์์ฑ์๋ฅผ ๋ช ์ํ์ง ์์ ๊ฒฝ์ฐ ์๋์ ์ผ๋ก ๋ํดํธ ์์ฑ์๊ฐ ์กด์ฌํ์ง๋ง, ๊ฐ๋ ์ฑ์ ์ํด ๋ช ์์ ์ผ๋ก ์ ์ธํด ์ฃผ์์ต๋๋ค.
1 2 3 4 5 6 7 8 9 10 11 | @NoArgsConstructor public class TestDto { private String id; private Long promotionId; private Long itemId; private String type; private String expiredStartDate; private String expiredEndDate; private String useYn; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 | @DisplayName("๊ธฐ๋ณธ ์์ฑ์๋ง ์กด์ฌํ ๊ฒฝ์ฐ ๋ฐ์ธ๋ฉ์ด ์ ์์ ์ผ๋ก ์ด๋ฃจ์ด์ง์ง ์๋๋ค.") @Test void givenNoArgsBinding_isNull() { final int expected = 2; List<TestDto> dtoList = noAliasMapper.findAll(); SoftAssertions.assertSoftly(softly -> { softly.assertThat(dtoList).hasSize(expected); softly.assertThat(dtoList.get(0)).isNull(); softly.assertThat(dtoList.get(1)).isNull(); }); } | cs |
2. ๊ธฐ๋ณธ ์์ฑ์(@NoArgs) + ๋ณ์นญ(Alias)
- 1)์๋ ๋ค๋ฅด๊ฒ ๊ธฐ๋ณธ ์์ฑ์์ ์ปฌ๋ผ Alias๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ, ์กฐํ ๊ฒฐ๊ณผ์ ๊ฐ์ฒด ๊ฐ ๋ฐ์ดํฐ ๋งคํ์ด ์ ์์ ์ผ๋ก ์งํ๋ฉ๋๋ค.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | -- AliasMapper.xml <?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.example.mybatisbinding.mapper.AliasMapper" > <select id="findAll" resultType="TestDto"> SELECT MC_ID AS id , P_ID AS promotionId , ITEM_ID AS itemId , MC_FG AS type , YH_E_YMD AS expiredEndDate , YH_S_YMD AS expiredStartDate , USE_YN AS useYn FROM TEST_TABLE WHERE MC_ID IN ('5716', '5717') -- 2๊ฑด์ ๋ฐ์ดํฐ ์กด์ฌ </select> </mapper> | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 | @DisplayName("๊ธฐ๋ณธ ์์ฑ์์ alias์ด ์กด์ฌํ ๊ฒฝ์ฐ ๋ฐ์ธ๋ฉ์ด ์ ์์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋ค.") @Test void givenNoArgsBindingWithAlias_isNotNull() { final int expected = 2; List<TestDto> dtoList = aliasMapper.findAll(); SoftAssertions.assertSoftly(softly -> { softly.assertThat(dtoList).hasSize(expected); softly.assertThat(dtoList.get(0)).isNotNull(); softly.assertThat(dtoList.get(1)).isNotNull(); }); } | cs |
- ์ฐธ๊ณ ๋ก alias์ ๊ฒฝ์ฐ ์ปฌ๋ผ์ ์์๊ฐ ์ค์ํ์ง ์๊ธฐ์ ๋ณ์นญ(alias)๋ง ๊ฐ์ฒด์ ํ๋๋ช ๊ณผ ๋์ผํ๋ค๋ฉด, ์์๋ ์ค์ํ์ง ์์ต๋๋ค.
3. ๋ชจ๋ ํ๋๋ฅผ ํฌํจํ๋ ์์ฑ์(@AllArgs)
- ๊ฐ์ฒด์ ๋ชจ๋ ํ๋๊ฐ ํฌํจ๋ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ(@AllArgs) ์กฐํ ๊ฒฐ๊ณผ์ ๊ฐ์ฒด ๊ฐ ๋ฐ์ดํฐ ๋งคํ์ด ์ ์์ ์ผ๋ก ์งํ๋ฉ๋๋ค.
1 2 3 4 5 6 7 8 9 10 11 | @AllArgsConstructor public class TestDto { private String id; private Long promotionId; private Long itemId; private String type; private String expiredStartDate; private String expiredEndDate; private String useYn; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?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.example.mybatisbinding.mapper.NoAliasMapper" > <select id="findAll" resultType="TestDto"> SELECT MC_ID , P_ID , ITEM_ID , MC_FG , YH_S_YMD , YH_E_YMD , USE_YN FROM TEST_TABLE WHERE MC_ID IN ('5716', '5717') -- 2๊ฑด์ ๋ฐ์ดํฐ ์กด์ฌ </select> </mapper> | cs |
- @AllArgs์ ๊ฒฝ์ฐ ์ปฌ๋ผ ์์๋๋ก ํ๋์ ๋งคํ์ด ๋๊ธฐ์ ์ปฌ๋ผ๊ณผ ํ๋์ ์์๋ฅผ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
1 2 3 4 5 6 7 8 9 10 11 12 13 | @DisplayName("๋ชจ๋ ํ๋์ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ ๋ฐ์ธ๋ฉ์ด ์ ์์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋ค.") @Test void givenAllArgsBinding_isNotNull() { final int expected = 2; List<TestDto> dtoList = noAliasMapper.findAll(); SoftAssertions.assertSoftly(softly -> { softly.assertThat(dtoList).hasSize(expected); softly.assertThat(dtoList.get(0)).isNotNull(); softly.assertThat(dtoList.get(1)).isNotNull(); }); } | cs |
3-1. ๊ฐ์ฒด์ ํ๋์ ์ปฌ๋ผ ์์๊ฐ ๋ค๋ฅผ ๊ฒฝ์ฐ → ์ํ์ง ์๋ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ ์ ์์ต๋๋ค.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?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.example.mybatisbinding.mapper.NoAliasMapper" > <select id="findAll" resultType="TestDto"> SELECT MC_ID , P_ID , ITEM_ID , MC_FG , YH_S_YMD , USE_YN -- YH_E_YMD ์ปฌ๋ผ๊ณผ ์์๊ฐ ๋ฐ๋ , YH_E_YMD FROM TEST_TABLE WHERE MC_ID IN ('5716', '5717') -- 2๊ฑด์ ๋ฐ์ดํฐ ์กด์ฌ </select> </mapper> | cs |
- USE_YN์ ์ปฌ๋ผ๊ณผ YH_E_YMD ์ปฌ๋ผ์ ๋ฐ์ดํฐ๊ฐ ๋ฐ๋์ด ๊ฐ์ฒด์ ๋งคํ์ด ๋์์ต๋๋ค.
- ์ปฌ๋ผ์ ํ์ ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ์ SQLException ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
4. ๊ธฐ๋ณธ ์์ฑ์ + ๋ชจ๋ ํ๋๋ฅผ ํฌํจํ๋ ์์ฑ์(@NoArgs + @AllArgs)
- @AllArgs ์ด๋ ธํ ์ด์ ์ด ์กด์ฌํ ๊ฒฝ์ฐ, ๋ํดํธ ์์ฑ์์ ์ฌ๋ถ๋ ์๊ด์์ด ๋งคํ์ด ์ ์์ ์ผ๋ก ๋ฉ๋๋ค.
1 2 3 4 5 6 7 8 9 10 11 12 | @NoArgsConstructor @AllArgsConstructor public class TestDto { private String id; private Long promotionId; private Long itemId; private String type; private String expiredStartDate; private String expiredEndDate; private String useYn; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 | @DisplayName("๊ธฐ๋ณธ ์์ฑ์์ ๋ชจ๋ ํ๋์ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ ๋ฐ์ธ๋ฉ์ด ์ ์์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋ค.") @Test void givenNoArgsAndAllArgs_isNotNull() { final int expected = 2; List<TestDto> dtoList = mapper.findAll(); SoftAssertions.assertSoftly(softly -> { softly.assertThat(dtoList).hasSize(expected); softly.assertThat(dtoList.get(0)).isNotNull(); softly.assertThat(dtoList.get(1)).isNotNull(); }); } | cs |
5. ์ฌ๋ฌ ๊ฐ์ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ
์ฌ๋ฌ ๊ฐ์ ์์ฑ์๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ @NoArgs์ @AllArgs๊ฐ ์กด์ฌํ๋ ์๋๋์ ๋ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง๋๋ค.
- ๊ธฐ๋ณธ ์์ฑ์๋ ์กด์ฌํ๋ alias๊ฐ ์์ ๊ฒฝ์ฐ - null๋ก ๋งคํ
- ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์กด์ฌํ์ง ์์ ๊ฒฝ์ฐ - alias ์ฌ๋ถ์ ์๊ด์์ด ์ด๋ ํ ์์ฑ์๋ฅผ ์ ํํด์ผ ํ ์ง ์ ์ ์๊ธฐ์ ์ค๋ฅ ๋ฐ์
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // ๊ธฐ๋ณธ ์์ฑ์์ ๋ชจ๋ ํ๋๋ฅผ ๊ฐ์ง ์์ฑ์๊ฐ ์๋, ์ฌ๋ฌ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ -> Exception ๋ฐ์ @ToString public class TestDto { private String id; private Long promotionId; private Long itemId; private String type; private String expiredStartDate; private String expiredEndDate; private String useYn; public TestDto(String id) { this.id = id; } public TestDto(String id, Long promotionId) { this.id = id; this.promotionId = promotionId; } } | cs |
6. ์ผ๋ถ ํ๋๋ฅผ ๊ฐ์ง๋ ๋จ ํ๋์ ์์ฑ์๋ง ์กด์ฌํ ๊ฒฝ์ฐ
- alias ์ค์ ์ด ์๋ ๊ฒฝ์ฐ: ์์ฑ์์ ์กด์ฌํ๋ ํ๋๋ง ๋งคํ์ด ๋ฉ๋๋ค.
- alias ์ค์ ์ด ์กด์ฌํ๋ ๊ฒฝ์ฐ: ๋ชจ๋ ํ๋์ ๋ํด ์ ์์ ์ผ๋ก ๋งคํ์ด ๋ฉ๋๋ค.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @ToString public class TestDto { private String id; private Long promotionId; private Long itemId; private String type; private String expiredStartDate; private String expiredEndDate; private String useYn; public TestDto(String id, Long promotionId) { this.id = id; this.promotionId = promotionId; } } | cs |
1 2 3 4 5 6 7 | @DisplayName("์ผ๋ถ ํ๋๋ง ๊ฐ์ง ์์ฑ์๊ฐ ์กด์ฌํ๊ณ , alias ์ค์ ์ด ์์ ๊ฒฝ์ฐ, ์ผ๋ถ ํ๋์ ๋ํด์๋ง ๋งคํ์ด ๋๋ค.") @Test void givenSomeFieldArgsWithNoAlias_isOnlySomeFieldsBinding() { List<TestDto> dtoList = aliasMapper.findAll(); System.out.println(dtoList); } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 | @DisplayName("์ผ๋ถ ํ๋๋ง ๊ฐ์ง ์์ฑ์๊ฐ ์กด์ฌํ๊ณ , alias ์ค์ ์ด ๋ ๊ฒฝ์ฐ, ๋ชจ๋ ํ๋๊ฐ ๋งคํ๋๋ค.") @Test void givenSomeFiledWithAlias_isNotNull() { List<TestDto> dtoList = aliasMapper.findAll(); System.out.println(dtoList); SoftAssertions.assertSoftly(softly -> { softly.assertThat(dtoList).hasSize(expected); softly.assertThat(dtoList.get(0)).isNotNull(); softly.assertThat(dtoList.get(1)).isNotNull(); }); } | cs |
์ ํ ์คํธ๋ฅผ ํ ๋๋ก ์ ๋ฆฌํด ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ํฉ์์๋ ๋ฐ์ธ๋ฉ์ด ์ ์์ ์ผ๋ก ์งํ์ด ๋ฉ๋๋ค.
- ๊ธฐ๋ณธ ์์ฑ์์ ๋ณ์นญ(alias)์ด ์กด์ฌํ๋ ๊ฒฝ์ฐ (@NoArgs + alias)
- ๋ชจ๋ ํ๋๋ฅผ ๊ฐ์ง๋ ์์ฑ์๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ (@AllArgs)
- ์์ฑ์๊ฐ ์ฌ๋ฌ ๊ฐ ์กด์ฌํ๋๋ผ๋, ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์กด์ฌํ๊ณ alias๊ฐ ์ค์ ๋ ๊ฒฝ์ฐ
์ ๋ฆฌํด ๋ณด๋ฉด, @AllArgs๊ฐ ์กด์ฌํ๊ฑฐ๋ ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ํฌํจํ์ฌ ๋ณ์นญ(Alias)๋ง ๊ฐ์ฒด ํ๋์ ๋์ผํ๋ค๋ฉด, ์์ฑ์์ ๊ฐ์์๋ ์๊ด์์ด ๋งคํ์ด ์ ์์ ์ผ๋ก ๋ฉ๋๋ค.
๊ฐ์ธ์ ์ธ ์๊ฐ์ผ๋ก @AllArgs๋ฅผ ํตํด ์ฌ์ฉํ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ๋จ์ ์ด ์กด์ฌํ๊ธฐ์ @NoArgs + Alias ์กฐํฉ์ผ๋ก ๋ฐ์ธ๋ฉ ํ๋ ๊ฒ ์ข์ ๋ฐฉ๋ฒ์ด ์๋๊น ์๊ฐํฉ๋๋ค.
(์๋ ์๊ฒฌ์ ํ์๋ถ๊ป์ ์ฃผ์ ์๊ฒฌ์
๋๋ค. ๐โ๏ธ)
- ์กฐํ ๊ฒฐ๊ณผ๊ฐ์ด ์ด๋ค ํ๋์ ๋งคํ๋์ด ์๋์ง ํ๋ํ๋ ๋น๊ตํ์ง ์์ผ๋ฉด ํ์ ์ด ํ๋ค๋ค.
- ์ถํ ์ปฌ๋ผ์ด๋ ์ฝ๋์ ๋ณ๊ฒฝ ์ @AllArgs๋ ์ปฌ๋ผ ์์๋ฅผ ์ ๊ฒฝ ์จ์ผ ํ๋ฏ๋ก ์ ์ง ๋ณด์ ๋ฉด์์ ๋น์ฉ์ด ๋ ๋ฐ์ํ ์ ์๋ค.
- alias๋ฅผ ํตํด ๊ฐ์ฒด์ ํ๋์ ์ปฌ๋ผ์ ์์๊ฐ ์ผ์นํ์ง ์๋๋ผ๋ ์ด๋ ํ ํ๋๊ฐ ๋งคํ๋๋์ง ๋ฐ๋ก ํ์ ํ ์ ์๋ค.
๊ทธ๋ผ ์ค์ ๋ด๋ถ์ ์ผ๋ก ์ด๋ ํ ๋ฐฉ์์ผ๋ก ์กฐํ ๊ฒฐ๊ณผ์ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ์ด ๋๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
โ๏ธ ๋งคํ ๊ณผ์
getter/setter์ ํ์์ฑ?
์์์ ๊ฐ์ฒด ํด๋์ค์ getter/setter๊ฐ ํ์ ์๋ค๊ณ ๋ง์๋๋ ธ๋๋ฐ์, ์ด๋ ๋ฆฌํ๋ ์ ์ ์ด์ฉํ์ฌ getter/setter๊ฐ ์กด์ฌํ์ง ์๋๋ผ๋ ์ค์ ์ ํด์ฃผ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฅํฉ๋๋ค.
Reflector Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class Reflector { ... public Reflector(Class<?> clazz) { type = clazz; addDefaultConstructor(clazz); Method[] classMethods = getClassMethods(clazz); addGetMethods(classMethods); // getter ๋ฉ์๋ ๋์์ผ๋ก ์ ๋ณด ์ทจํฉ addSetMethods(classMethods); // setter ๋ฉ์๋ ๋์์ผ๋ก ์ ๋ณด ์ทจํฉ addFields(clazz); // field ๋์์ผ๋ก ์ ๋ณด ์ทจํฉ readablePropertyNames = getMethods.keySet().toArray(new String[0]); writablePropertyNames = setMethods.keySet().toArray(new String[0]); for (String propName : readablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); // ๋๋ฌธ์ ์ค์ } for (String propName : writablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); // ๋๋ฌธ์ ์ค์ } } | cs |
TestDto ํด๋์ค์๋ private ํ๋๋ง ์กด์ฌํ ๋ฟ getter์ setter๊ฐ ๋ฐ๋ก ์กด์ฌํ์ง ์๋๋ฐ์, ์ด๋ ๋ฆฌํ๋ ์ (Reflector)์ ์ด์ฉํ์ฌ resultType์ ํด๋์ค์ ๋ํ ํ๋ ์ ๋ณด ๋ฐ getter, setter์ ๋งคํ ์ ๋ณด๋ฅผ ์์ฑํด๋๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ํ์๊ฐ ์์ต๋๋ค.
- ์ ์ฝ๋๋ Reflector ํด๋์ค์ ์์ฑ์์ ๋๋ค.
- getter์ setter์ ๋ํ ๋ฉ์๋๊ฐ ์กด์ฌํ๋ฉด, addGetMethods(), addSetMethods() ๋ฉ์๋์์ getter/setter ์ฒ๋ฆฌ๋ฅผ ๋จผ์ ์งํํฉ๋๋ค.
- ๋ง์ฝ getter, setter ์ ๋ณด๊ฐ ์๋ค๋ฉด addFields() ๋ฉ์๋์์ ํ๋ ์ ๋ณด๋ฅผ ํ ๋๋ก getter/setter๋ฅผ ์๋ก ๋ง๋ค๊ธฐ์ ํด๋์ค์ getter/setter๋ฅผ ์ ์ธํด ์ฃผ์ง ์์๋ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
- ๋ํ ์ปฌ๋ผ๊ณผ ํ๋์ ๋์๋ฌธ์๊ฐ ๋ค๋ฅด๋๋ผ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์๋๋ฐ์, ์ด๋ ์ ์ฝ๋์์ toUpperCase() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋๋ฌธ์๋ก ๋ชจ๋ ๋ณ๊ฒฝํด๋ฒ๋ฆฌ๊ธฐ์ ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ์์ต๋๋ค.
Reflector - addGetMethods(), addSetMethods(), addFields()
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | public class Reflector { ... // ๋ฉ์๋๋ฅผ ํ ๋๋ก getter ์ค์ private void addGetMethods(Method[] methods) { Map<String, List<Method>> conflictingGetters = new HashMap<>(); Arrays.stream(methods) .filter(m -> m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName())) .forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m)); resolveGetterConflicts(conflictingGetters); } ... // ๋ฉ์๋๋ฅผ ํ ๋๋ก setter ์ค์ private void addSetMethods(Method[] methods) { Map<String, List<Method>> conflictingSetters = new HashMap<>(); Arrays.stream(methods) .filter(m -> m.getParameterTypes().length == 1 && PropertyNamer.isSetter(m.getName())) .forEach(m -> addMethodConflict(conflictingSetters, PropertyNamer.methodToProperty(m.getName()), m)); resolveSetterConflicts(conflictingSetters); } ... // ํ๋๋ฅผ ํ ๋๋ก getter/setter ์ค์ private void addFields(Class<?> clazz) { Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (!setMethods.containsKey(field.getName())) { // issue #379 - removed the check for final because JDK 1.5 allows // modification of final fields through reflection (JSR-133). (JGB) // pr #16 - final static can only be set by the classloader int modifiers = field.getModifiers(); if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) { addSetField(field); } } if (!getMethods.containsKey(field.getName())) { addGetField(field); } } if (clazz.getSuperclass() != null) { addFields(clazz.getSuperclass()); } } | cs |
ํ ์คํธ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์๋ ์ผ์ด์ค์ ๋ํด ๋งคํ๋๋ ๊ณผ์ ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๐
- ๊ธฐ๋ณธ ์์ฑ์(@NoArgsConstructor)
- ๊ธฐ๋ณธ ์์ฑ์(@NoArgsConstructor) + ๋ณ์นญ(Alias)
- ๋ชจ๋ ํ๋๋ฅผ ํฌํจํ๋ ์์ฑ์(@AllArgsConstructor)
- ๊ธฐ๋ณธ ์์ฑ์ + ๋ชจ๋ ํ๋๋ฅผ ํฌํจํ๋ ์์ฑ์(@NoArgs + @AllArgs)
- ์ฌ๋ฌ ๊ฐ์ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ
- ์ผ๋ถ ํ๋๋ฅผ ๊ฐ์ง๋ ๋จ ํ๋์ ์์ฑ์๋ง ์กด์ฌํ ๊ฒฝ์ฐ
1. ๊ธฐ๋ณธ ์์ฑ์๋ง ์กด์ฌํ ๋ ๋งคํ๋๋ ๊ณผ์
MyBatis์ Mapper๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ๋, ResultSetHandler์ ๊ตฌํ์ฒด์ธ DefaultResultSetHandler ํด๋์ค์์ ์กฐํ ๋ฐ ๋งคํ ์ฒ๋ฆฌ๋ฅผ ์งํํฉ๋๋ค.
- ์์ ๊ฐ์ด DefaultResultSetHandler ํด๋์ค์ ์์ฑ์์์ ์ฟผ๋ฆฌ ์คํ๊ณผ ๊ด๋ จ๋ ์ฌ๋ฌ ์ค์ ๋ค์ ์งํํฉ๋๋ค.
- ์บ์ฑ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๋ณด, offset, limit, ์ฟผ๋ฆฌ ์ ๋ณด, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ์ ์ ๋ณด, ๋งคํํ๋ ค๋ ๊ฐ์ฒด์ ํด๋์ค ์ ๋ณด ๋ฑ์ ๋ฐ์ดํฐ๊ฐ ์ค์ ๋ฉ๋๋ค.
- DefaultResultSetHandler ํด๋์ค ์ด๊ธฐํ ํ ์ฌ๋ฌ ๊ณผ์ ์ ๊ฑฐ์ณ getRowValue() ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
DefaultResultSetHandler - getRowValue()
- getRowValue() ๋ฉ์๋์์ ์ค์ ๋ฐ์ดํฐ(Object)๋ฅผ ์์ฑํ๋ ๋ถ๋ถ์ 398๋ผ์ธ์ ์ฝ๋์ ๋๋ค.
DefaultResultSetHandler - createResultObject()
- ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ, ์ ์ฌ์ง์์ 656๋ผ์ธ์ objectFactory.create() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋ฆฌํดํฉ๋๋ค.
DefaultObjectFactory - create()
- ๊ธฐ๋ณธ ์์ฑ์์ธ ๊ฒฝ์ฐ, ์ต์ด 44๋ผ์ธ์ create() ๋ฉ์๋๋ฅผ ํธ์ถํ๋๋ฐ์, constructorArgTypes์ constructorArgs๊ฐ null์ธ ์ํ๋ก 50 ๋ผ์ธ์ create() ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
- ๊ทธ ํ instantiateClass() ๋ฉ์๋์์ ์์ฑ์ ์ธ์์ ๊ด๋ จ๋ ๊ฐ๋ค์ด ๋ชจ๋ null์ด๊ธฐ ๋๋ฌธ์ 62๋ผ์ธ์ constructor.newInstance() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋ฆฌํดํฉ๋๋ค..
- ๊ฒฐ๊ตญ ์์ฑ์์ ์ ๋ณด๊ฐ ์๋ฌด๊ฒ๋ ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์, ๊ฐ์ฒด์ ๋ชจ๋ ํ๋๊ฐ null์ธ ์ํ๋ก ๋ฆฌํด์ด ๋ฉ๋๋ค.
2. ๊ธฐ๋ณธ ์์ฑ์์ alias๊ฐ ์กด์ฌํ ๋
๊ธฐ๋ณธ ์์ฑ์์ alias๊ฐ ์กด์ฌํ๋๋ผ๋ 2. ๊ธฐ๋ณธ ์์ฑ์๋ง ์กด์ฌํ ๋์ ๋์ผํ ์ด์ ๋ก resultObject ๋ฐ์ดํฐ๋ ๋ชจ๋ null๋ก ๋งคํ์ด ๋์ง๋ง, ์ดํ ์ฒ๋ฆฌ ๊ณผ์ ์ด ๋ค๋ฆ ๋๋ค.
DefaultResultSetHandler - getRowValue()
- ์ ์ฝ๋์์ applyAutomaticMappings() ๋ฉ์๋ ๋ด๋ถ์์ alias๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ ๋ค๋ฅด๊ฒ ๋์ํฉ๋๋ค.
- applyAutomaticMappings() ๋ฉ์๋์ ์ํด ์ปฌ๋ผ alias๊ฐ ์ ์ฉ๋ ๊ฒฝ์ฐ ์ ์์ ์ผ๋ก ๋ฐ์ดํฐ๊ฐ ๋งคํ์ด ๋๋๋ฐ์, ํด๋น ๋ฉ์๋์์ autoMapping์ ์์ ์ด ์ด๋ฃจ์ด์ง๋๋ค.
- ์ ์ฌ์ง์์ ์ข์ธก์ด alias๊ฐ ์ค์ ๋์ง ์์ ๊ฒฝ์ฐ์ด๊ณ , ์ฐ์ธก์ด alias๊ฐ ์ค์ ๋ ๊ฒฝ์ฐ์ ๋๋ค. ์ค์ alias๋ก ์ธํด ์ปฌ๋ผ ๋ค์๊ณผ TestDto ๊ฐ์ฒด์ ํ๋๊ฐ ๋๋ฌธ์๋ก ๋์ผํ๊ฒ ์ค์ ์ด ๋๊ณ , ์ดํ autoMapping ๋ฆฌ์คํธ์ ์ปฌ๋ผ์ ๋ณด๋ฅผ ๋ชจ๋ add ํฉ๋๋ค. (541 ๋ผ์ธ)
- ๊ทธ ํ autoMapping์ ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ฉฐ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๊ณ ๊ฐ์ฒด์ ๋งคํ์ด ์ด๋ฃจ์ด์ง๋๋ฐ์, ์์ ๊ฐ์ ๊ณผ์ ์ ํตํด alias๊ฐ ์ค์ ๋ ๊ฒฝ์ฐ ์ต์ด resultObject๋ null์ด์ง๋ง autoMapping์ ํตํด ์ค์ ์ ์ผ๋ก๋ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ๊ณผ ๋งคํ์ด ๋ฉ๋๋ค.
3, 4. ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์๋ ๊ฒฝ์ฐ
์ด๋ฌํ ์ผ์ด์ค๋ ์์ 2. ๊ธฐ๋ณธ ์์ฑ์ ํน์ ๊ธฐ๋ณธ 3. ์์ฑ์ + alias๊ฐ ์กด์ฌํ ๋์ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌ๋ฉ๋๋ค.
DefaultResultSetHandler ํด๋์ค์์ getRowValue() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฑด ๋์ผํ์ง๋ง, ์ดํ createResultObject() ๋ฉ์๋ ํธ์ถ ์ ๋ค๋ฅด๊ฒ ๋์ํฉ๋๋ค.
- ์ ์ฝ๋์์ ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ 656 ๋ผ์ธ์ objectFactory.createI() ๋ฉ์๋๋ฅผ ํธ์ถํ์์ผ๋, @AllArgs๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ ๊ทธ ๋ค์์ 658 ๋ผ์ธ์ธ createByConstructorSignature() ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
DefaultResultSetHandler - createByConstructorSignature()
- ์์์ ์์ฑ์์ ํ๋ผ๋ฏธํฐ ํ์ ์ ๋ฐ๋ณตํ๋ฉด์ ์ปฌ๋ผ์ ๋ํ ์ ๋ณด ๋ฐ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ์ constructorArgType, constructorArgs ๋ณ์์ add ํฉ๋๋ค.
- ๊ฒฐ๊ตญ ์ ๋ฉ์๋๋ objectFactory.create() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฑด ๊ธฐ๋ณธ ์์ฑ์์ ๋ก์ง๊ณผ ๋์ผํ์ง๋ง, ์ฐจ์ด์ ์ ์์ฑ์์ ๋ํ ์ ๋ณด๊ฐ null์ด ์๋ ์ํ๋ก create() ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
DefaultObjectFactory - create()
- ๊ธฐ๋ณธ ์์ฑ์๋ง ์กด์ฌํ๋ ๊ฒฝ์ฐ์๋ ๋ฌ๋ฆฌ, ์์ฑ์ ์ธ์์ ํ์ ๊ณผ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์กด์ฌํ ๋์ 62๋ผ์ธ์ ํธ์ถํ๋ ๊ฒ ์๋, 74๋ผ์ธ์ ํธ์ถํ์ฌ ์์ฑ์ ์ธ์์ ๋ฐ์ดํฐ๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
โป ๋ฐ๋ผ์, ์ผ๋ถ ํ๋๋ง ํฌํจํ๋ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ, ์์ฑ์์ ์กด์ฌํ๋ ํ๋๋ง ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ด ๋๊ณ , ๋๋จธ์ง ํ๋๋ null๋ก ๋งคํ๋ฉ๋๋ค.
5. ์ฌ๋ฌ ๊ฐ์ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ
์ ํ ์คํธ์์ ์ดํด๋ณด์๋ 5) ์ฌ๋ฌ ๊ฐ์ ์์ฑ์๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ์ ๋ํ ๋ถ์์ ๋๋ค.
- ์์ ๊ฒฝ์ฐ DefaultResultSetHandler ํด๋์ค์ createByConstructorSignature() ๋ฉ์๋์์ ์ด๋ ํ ์์ฑ์๋ฅผ ์ ํํด์ผ ํ ์ง ์ ์ ์๊ธฐ์ Exception ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
- ๋ชจ๋ ํ๋์ ์์ฑ์(@AllArgs)๊ฐ ์กด์ฌํ ๋ ์ ์์ธ๊ฐ ๋ฐ์ํ์ง ์๋ ์ด์ ๋ ์ if๋ฌธ์ allowedConstructorUsingTypeHandlers() ๋ฉ์๋ ๋ด๋ถ์์ ์์ฑ์์ ํ๋ ๊ฐฏ์๊ฐ ๋ชจ๋ ํ๋์ ๊ฐฏ์๋ฅผ ๋น๊ตํ์ฌ ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
6. ์ผ๋ถ ํ๋๋ฅผ ๊ฐ์ง๋ ๋จ ํ๋์ ์์ฑ์๋ง ์กด์ฌํ ๊ฒฝ์ฐ
ํด๋น ์ผ์ด์ค๋ 4. ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์๋ ๊ฒฝ์ฐ ์ ๋์ผํ๊ฒ ์๋ํ์ฌ ์์ฑ์์ ์กด์ฌํ๋ ํ๋์ ๋ํด์๋ง ๋งคํ์ด ์ด๋ฃจ์ด์ง๋๋ค.
๐ก ์ ๋ฆฌ
๋ฌผ๋ก ์ฒ์๋ถํฐ ๋๊น์ง ๋ชจ๋ ์ฝ๋๋ฅผ ์ดํด๋ณธ ๊ฑด ์๋์ง๋ง, ๊ฐ์ฒด์ ๋งคํ์ด ์ด๋ฃจ์ด์ง๊ธฐ๊น์ง ๋ค์ํ ๊ณผ์ ์ ํตํด ์งํ๋๋ ๊ฒ์ ์ ์ ์์์ต๋๋ค.
์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์ ๊ฐ์ฒด์ ๋งคํ์ ํ ๋ @AllArgs๋ฅผ ์ฌ์ฉํ์ฌ ๋ถํ์ํ ์ฝ๋(alias)๋ ์์ ๋ ๊ฒ ์ข์ง ์์๊น๋ผ๊ณ ์๊ฐํ์๋๋ฐ, ํ์๋ถ์ด ๋ง์ํด ์ฃผ์ ๋๋ก ์ ์ง ๋ณด์ ์ธก๋ฉด์์๋ @NoArgs + alias์ ์กฐํฉ์ ์ฌ์ฉํ์ฌ ๋ณ๊ฒฝ ๊ฐ๋ฅ์ฑ์๋ ์ ์ฐํ๊ฒ ๊ฐ์ ธ๊ฐ๋ ๊ฒ์ด ์ข์ง ์์๊น ์๊ฐํฉ๋๋ค.
๐ ์ฐธ๊ณ ๋ฌธ์
- https://mybatis.org/mybatis-3/sqlmap-xml.html
- https://jasper-rabbit.github.io/posts/mybatis-refector/
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
SpringBoot Multi DataSource - JPA (0) | 2023.01.21 |
---|---|
Spring AOP๋ฅผ ์ฌ์ฉํ์ฌ ํด๋ผ์ด์ธํธ์ ์์ฒญ ์ ๋ณด ๋ก๊น ํ๊ธฐ (0) | 2023.01.14 |
JUnit5 assertThat vs assertAll vs assertSoftly (3) | 2022.09.17 |
Spring Boot profiles ์ค์ ํ๊ธฐ (1) | 2022.09.05 |
Spring Thread, Transaction, Connection ๊ด๊ณ (0) | 2022.09.03 |
๋๊ธ