๊ด๋ฆฌ์ ์ ๋ณด๋ฅผ ์์ ํ๋๋
์ค๋ณต ์ ์ฅ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
์๋ฌ์ ์์ธ์ ์ฐพ๊ณ ์์ ํด๋ณด์.
1. ์๋ฌ
Duplicate entry '2-3' for key 'admin_permission.uk_admin_permission'
์ฒ์ ๋ก์ง์ ์ด๋ฌ๋ค. [ ๊ด๋ฆฌ์ ์ ๋ณด ์์ ] - [ ๊ธฐ์กด ๊ถํ ์ญ์ ] - [์ ๊ถํ ๋ค์ ์ ์ฅ] ํ๋ฆ์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ค. ๊ทธ๋ฐ๋ฐ ์๊ฐํ ํ๋ฆ๋๋ก ์ผ์ฒ๋ฆฌ๊ฐ ๋์ง ์์ ๋ชจ์์ด๋ค. ์ด๋์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋์ง DB๋ถํฐ ๋ค์ ์ดํด๋ดค๋ค.
AdminService์ update ์ฝ๋ ์ค ์ผ๋ถ // ๊ธฐ์กด ๊ถํ ์ญ์ adminPermissionRepository.deleteByAdminId(id); // ๋ค์ ์ ์ฅ savePermissions(id, request.getPermissions());โDB๋ฅผ 3๊ฐ๋ก ๋ถ๋ฆฌํด๋๋ค. ๊ด๋ฆฌ์์ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ Admin, ๊ถํ ์ข ๋ฅ๋ฅผ ์ ์ฅํ๋ Permission, ๊ด๋ฆฌ์์ ๊ถํ์ ์ฐ๊ฒฐํด์ฃผ๋ ์ค๊ฐ ํ ์ด๋ธ์ธ AdminPermission. ๊ทธ๋ฆฌ๊ณ admin_permission ํ ์ด๋ธ์๋ ์ ๋ํฌ ์ ์ฝ์ ๊ฑธ์ด์ ๊ด๋ฆฌ์์ ๊ถํ์ ์กฐํฉ์ด ์ค๋ณต๋ ์ ์๋๋ก ์ค์ ํ๋ค.
๊ทธ๋ฐ๋ฐ Duplicate entry '2-3'์ admin_id = 2์ permission_id = 3์ ์กฐํฉ์ด ์ค๋ณต๋์๋ค๊ณ ์๋ ค์ค ๊ฒ์ด๋ค. ์๋ฅผ ๋ค์ด์ 2๋ฒ ๊ด๋ฆฌ์๊ฐ 3๋ฒ ๊ถํ์ธ ADD ๊ถํ์ ๊ฐ๊ณ ์๋๋ฐ, ์ด 2-3 ์กฐํฉ์ ๋ค์ ํ ๋ฒ insertํ๋ ค๊ณ ํ๋ค๋ ์ด์ผ๊ธฐ๋ค. ์ด๋ฐ ์ผ์ด ๋ฐ์ํ ์ด์ ๋ ์๋ง๋ ๊ธฐ์กด ๊ถํ ์ญ์ ๊ฐ ์ ๋๋ก ์ด๋ค์ง์ง ์์๊ฒ ์๋๊น๋ผ๊ณ ์ถ์ธกํ๋ค.
2. flush( )
- ์์์ฑ ์ปจํ ์คํธ(Persistence Context)์ ๋ณ๊ฒฝ ๋ด์ฉ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋๊ธฐํํ๋ ์์ ์ ๋งํ๋ค.
- ์ฝ๊ฒ ๋งํด์, ๋ฉ๋ชจ๋ฆฌ์์์ ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ๋ค์ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฟผ๋ฆฌ(SQL)๋ก ๋ ๋ ค ์ํ๋ฅผ ๋๊ฐ์ด ๋ง์ถ๋ ๊ณผ์ ์ด๋ค.
- JPA๋ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํด ์ฟผ๋ฆฌ๋ฅผ ๋ฐ๋ก ๋ ๋ฆฌ์ง ์๊ณ ์ฐ๊ธฐ ์ง์ฐ์ด๋ ๊ฐ๋ ์ ์ฌ์ฉํ๋ค.
- flush( )๊ฐ ๋ฐ์ํ๋ฉด ์ฐ๊ธฐ ์ง์ฐ ๋๋ฌธ์ ๋ฐ๋ ค์๋ INSERT, UPDATE ๋ฑ ์ฟผ๋ฆฌ๋ค์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก ๋ ์๊ฐ๋ค.
Q. flush( )๋ ์ธ์ ๋ฐ์ํ๋๊ฐ?
A. ์์์ ์ค๋ช ํ ๊ฒ๊ณผ ๊ฐ์ด JPA๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ํ ์ ๊ทผ์ ์ต์ํํ์ฌ ์ฑ๋ฅ์ ๋์ด๊ธฐ ์ํด ์ฐ๊ธฐ ์ง์ฐ์ด๋ผ๋ ๊ฐ๋ ์ ์ฌ์ฉํ๋ค. ๊ฐ๋ฐ์๊ฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฑฐ๋ ์์ , ์ญ์ ํด๋ ์ฆ์ DB์ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ์ง ์๋๋ค. ๋์ ์์์ฑ ์ปจํ ์คํธ ๋ด๋ถ์ ์ฐ๊ธฐ ์ง์ฐ SQL ์ ์ฅ์์ ์ฟผ๋ฆฌ(INSERT, UPDATE, DELETE)๋ฅผ ์ฐจ๊ณก์ฐจ๊ณก ๋ชจ์ ๋๋ค. ์ด ๋ชจ์๋ ์ฟผ๋ฆฌ๋ฅผ ํ ๋ฒ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก ์์๋ด๋ ์์ ์ด ๋ฐ๋ก flush( )์ด๋ค.
flush( )๋ ๊ฐ๋ฐ์๊ฐ ๋ช ์์ ์ผ๋ก ํธ์ถํ ์๋ ์์ง๋ง, ๋๋ถ๋ถ ํ๋ ์์ํฌ์ ์ํด ์๋์ผ๋ก ๋ฐ์ํ๋ค. @Transcational ๋ฉ์๋๊ฐ ์ ์์ ์ผ๋ก ๋๋๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ปค๋ฐ์ ํ๊ธฐ ์ง์ ์ ์๋์ผ๋ก ํธ์ถ๋๋ค. JPQL์ด๋ QueryDSL ๋ฑ์ ํตํด DB์ ์ง์ ์กฐํ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๊ธฐ ์ง์ ์ ์๋์ผ๋ก ํธ์ถ๋๋ค. ๋ฉ๋ชจ๋ฆฌ์๋ง ์๊ณ DB์๋ ๋ฐ์๋์ง ์์ ๋ฐ์ดํฐ ๋๋ฌธ์ ์๋ชป๋ ๊ฒฐ๊ณผ๊ฐ ์กฐํ๋๋ ๊ฒ์ ๋ง๊ธฐ ์ํด์์ด๋ค. ์ง์ ํธ์ถํ๋ ๊ฒฝ์ฐ๋, repository.flush( ) ๋ฑ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
3. ์๋ฌ ๊ณ ์น๊ธฐ
- AdminService
// ๊ธฐ์กด ๊ถํ ์ญ์
adminPermissionRepository.deleteByAdminId(id);
// ์ญ์ ๋ด์ฉ์ DB์ ๋ฐ์
adminPermissionRepository.flush();
// ์ ๊ถํ ๋ค์ ์ ์ฅ
savePermissions(id, request.getPermissions());
๊ธฐ์กด ๊ถํ์ ์ญ์ ๋ฅผ ํ๊ณ ๋๋ฉด flush( )๋ก ์ญ์ SQL์ ๊ฐ์ ๋ก ๋จผ์ ์คํ์์ผ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋๊ฑธ ๋ง๋๋ก ํ๋ค.
Q. ์ด ์ฝ๋๋ ๊ฝค ๊ด์ฐฎ์ ์ฝ๋์ผ๊น?
A. flush( )๋ฅผ ์ฌ์ฉํด์ ์ค๋ฅ๋ฅผ ์ผ์์ ์ผ๋ก ๊ณ ์น๊ธด ํ์ง๋ง, ์ด ์ฝ๋๊ฐ ๊ฝค ๊ด์ฐฎ์๊ฑด์ง์ ๋ํด์๋ ์ ๋ชจ๋ฅด๊ฒ ๋ค. ์ด ์ฝ๋๋ ํ ์ด๋ธ ์ค์ฌ ์ฝ๋์ด๋ค. ์ง์ ํ ์ด๋ธ์ ๊ฑด๋๋ฆฐ๋ค๋ ๋ง์ด๋ค. admin_permission ํ ์ด๋ธ์ admin_id, permission_id ํ์ ์ง์ ์ญ์ /์ฝ์ ํ๊ณ ์๋ค. ์ด๊ฑด SQL ํ ์ด๋ธ์ ์๋์ผ๋ก ๋ค๋ฃจ๊ณ ์๋ ๊ฒ์ด๋ค.
์ฒ์์ ์ฝ๋๋ฅผ ์์ฑํ์๋, [ ๊ด๋ฆฌ์ ์ ๋ณด ์์ ] - [ ๊ธฐ์กด ๊ถํ ์ญ์ ] - [ ์ ๊ถํ ๋ค์ ์ ์ฅ ]์ด ์ ์ ๋ก ๋ ๊ฑฐ๋ผ๊ณ ์๊ฐํ์ง๋ง ์๋์๋ค. ๋ flush( )๋ ํ๋ ์์ํฌ์์ ์๋์ผ๋ก ํธ์ถ์ด ๋์ด์ผํ๋ค. ๊ทธ๋ผ ์ ์๋๊ฑด์ง์ ๋ํด์ ์๊ฐํด๋ด์ผํ๋๋ฐ, ๊ทธ ์ด์ ๊ฐ ํ ์ด๋ธ์ ์ง์ ์ ์ผ๋ก ๊ฑด๋๋ฆฌ๊ณ ์ธ๋ํค ID๋ฅผ ์ง์ ๋ฃ๋ ๊ฒ์ด ๋ฌธ์ ์ธ๊ฒ ์๋์ง ์ถ์ธกํด๋ณผ ์ ์๋ค.
// ์ธ๋ํค๋ฅผ ์ง์ ๋ฃ์ ์ฝ๋ adminPermission.setAdminId(adminId); adminPermission.setPermissionId(permission.getId());
JPA๋ ์๋ ํ ์ด๋ธ ํ์ ์ง์ ์กฐ์ํ๊ธฐ๋ณด๋ค ์ํฐํฐ ๊ฐ์ฒด์ ์ํ์ ๊ด๊ณ๋ฅผ ๋ฐ๊พธ๋ฉด Hibernate๊ฐ SQL๋ก ๋ณํํด์ฃผ๋ ๊ตฌ์กฐ์ด๋ค. ๊ทธ๋ฌ๋๊น ์ง๊ธ ์ฝ๋๋ JPA๋ฅผ ์ ๋๋ก ํ์ฉํ์ง ๋ชปํ๋ค๊ณ ๋ด์ผํ๋ค.// ์ํฐํฐ ๊ด๊ณ๋ฅผ ๋ช ํํ๊ฒ ํ ์ฝ๋ adminPermission.setAdmin(admin); adminPermission.setPermission(permission);
์์ ์ฝ๋์ฒ๋ผ ๋ฐ๊พผ๋ค๋ฉด ๊ฐ์ฒด ๊ด๊ณ๊ฐ ์ฝ๋์์์ ๋ค์ด๋๊ฒ ๋๋ค. ๊ทธ๋ฌ๋ฉด ํ ์ด๋ธ ์ค์ฌ ์ฝ๋์์ ๊ฐ์ฒด ๊ด๊ณ ์ค์ฌ ์ฝ๋๋ก ๋ณ๊ฒฝ๋ ์ ์๋ค. ๋ฌผ๋ก ์์ ์ฝ๋๋ก ๋ฐ๊พธ๋ ค๋ฉด ์ ๋ฐ์ ์ธ ์์ ์ด ํ์ํ ๊ฒ์ด๋ค.