๋ชฉ์ฐจ
๋ฐ๋๋ฝ์ด ๋ฐ์ํ ์ด์
์ ํฌ ์๋น์ค์์๋ ํฌํ/์ฝ์์ก๊ธฐ ๋ชฉ๋ก ์กฐํ์ ํฌํ ๋๋ ์ฝ์์ก๊ธฐ๋ฅผ ๋ง์น ์ธ์์ ์๋ฅผ ํ์ํ๋ ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ๊ธฐ์กด์๋ ์ฐ๊ด ๊ด๊ณ๋ก ๋งคํ๋ ๊ฒฐ๊ณผ ํ
์ด๋ธ์์ ํด๋น ํฌํ ๋๋ ์ฝ์์ก๊ธฐ์ id ๋ก ์กฐํํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ์ ์๋ฅผ ์ธ๋ ๋ก์ง์ด์์ต๋๋ค. ํ์ง๋ง ๋ฐ์ดํฐ๊ฐ ์์ด๋ฉด ์์ผ์๋ก ์กฐํ ์ฑ๋ฅ์ด ์ ํ๊ฐ ๋๋ ๋จ์ ์ ๋ฐ๊ฒฌํ๊ณ , ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํฌํ/์ฝ์์ก๊ธฐ๋ฅผ ๋ง์น ์ธ์์ ์๋ฅผ update ํ๋ selected_count ์นผ๋ผ์ ์ถ๊ฐํ๋ ๋ฐ์ ๊ทํ๋ฅผ ์งํํ์์ต๋๋ค. ๋ฐ์ ๊ทํ๋ฅผ ํ ํฌํ/์ฝ์์ก๊ธฐ ์งํ ์์ ๋ก์ง์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
1.
ํฌํ/์ฝ์์ก๊ธฐ ์กฐํ
2.
ํฌํ/์ฝ์์ก๊ธฐ ์ ํ ๊ฒฐ๊ณผ ๋ ์ฝ๋ ์ฝ์
3.
ํฌํ/์ฝ์์ก๊ธฐ selected_count + 1 ์์
์ฒ์ ์ด๋ฐ ํ๋ก์ธ์ค๋ฅผ ๊ตฌ์ฑํ ๋น์์๋ ์ด ๊ณผ์ ์์ ๋์์ฑ๊ณผ ๊ด๋ จ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค๋ ์ฌ์ค์ ์ธ์งํ์ง ๋ชปํ๊ณ ๋์ด๊ฐ์ต๋๋ค. ์ด๋ค ๋์์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊น์?
๋ฐ์ ๊ทํ ํ๋ฉด์ ์๊ฒจ๋ ์ ์๋ ๋ฐ๋๋ฝ ๋ฌธ์
์ ํฌ ๋ก์ง์ ํฌํ/์ฝ์์ก๊ธฐ ์งํ ์ ํด๋น ๋ฉค๋ฒ๊ฐ ์์ง ์งํํ์ง ์์ ๋ฉค๋ฒ๋ผ๋ฉด selected_count ๋ฅผ +1 ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด JPA ๋ ํธ๋์ญ์
์ปค๋ฐ ์ข
๋ฃ ์์ ๋๋ ์์์ฑ ์ปจํ
์คํธ์ flush๊ฐ ์ผ์ด๋๋ ์์ ์ ์ํฐํฐ์ ์ค๋
์ท์ ๋น๊ตํ๋ ๋ํฐ ์ฒดํน์ ํ๊ณ ๋ณ๊ฒฝ๋ ์ปฌ๋ผ์ด ์์ผ๋ฉด ๋ณ๊ฒฝ๋ ์ํฐํฐ์ ๋ํด update ์ฟผ๋ฆฌ๋ฅผ ์คํํฉ๋๋ค. ์ง์ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ์ง ์๊ณ JPA ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ์ต๋ํ ๋๋ฉ์ธ ๊ฐ์ฒด ๋ด๋ถ์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ง๋ค์ด ์์ง๋๋ฅผ ๋์ผ ์ ์๋๋ก ํ์์ต๋๋ค.
๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ง์
์์ 1, 2, 3 ๋ก์ง์ ํ๋์ ํธ๋์ญ์
๋ด์์ ์์ฐจ์ ์ผ๋ก ์งํ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ 2๋ฒ ๋ก์ง์์ ์ ํ ๊ฒฐ๊ณผ๋ฅผ ์ฝ์
ํ ๋์๋, ์ฃผ ํ
์ด๋ธ์ ์ธ๋ํค๋ฅผ ํจ๊ป ์ ์ฅํฉ๋๋ค. ์ด ๋ถ๋ถ์ผ๋ก ๊ธฐ์ธํ์ฌ ๋์์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์์ต๋๋ค. ์ ํฌ๊ฐ ์ฌ์ฉํ๊ณ ์๋ MySQL ์ Inno DB ์ ํน์ฑ์, ์ฐ๊ด๊ด๊ณ์ ์๋ ํ
์ด๋ธ์ ๋ ์ฝ๋ ์ฝ์
์ ์ฐ๊ด๊ด๊ณ์ ์๋ ๋ ์ฝ๋์ ๊ณต์ ๋ฝ์ ์ก์ต๋๋ค.
โข
์ฝ์์ก๊ธฐ
โข
์ฝ์์ก๊ธฐ ์ ํ ๊ฒฐ๊ณผ
id | title | selected_count |
1 | ํ์ ๋ ์ง | 0 |
2 | ์คํฐ๋ ์๊ฐ | 0 |
id | appointment_id |
1 | 1 |
2 | 1 |
์ฝ์์ก๊ธฐ ์ ํ ๊ฒฐ๊ณผ์ ๋ ์ฝ๋๋ฅผ ์ฝ์
ํ ๋ ์ธ๋ํค(appointment_id 1)๋ ์ ์ฅํ๋๋ฐ, ์ด ์ธ๋ํค์ ์๋ ๋ ์ฝ๋์ธ ์ฝ์์ก๊ธฐ์ id๊ฐ 1์ธ ๋ ์ฝ๋์ ๊ณต์ ๋ฝ์ ํ๋ํฉ๋๋ค.
start transaction;
insert into appointment_available_time values (null, 1);
select * from performance_schema.data_locks;
SQL
๋ณต์ฌ
lock_mode ์ปฌ๋ผ์ ๋ณด๋ฉด S ๋ผ๋ ๊ณต์ ๋ฝ(Shared lock)๊ณผ, REC_NOT_GAP ์ด๋ผ๋ ๊ฐญ๋ฝ์ด ์๋ ๋ ์ฝ๋๋ฝ ์ ํ๋ํ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ดํ 3๋ฒ ๋ก์ง์์ ์ฝ์์ก๊ธฐ์ ํด๋น ๋ ์ฝ๋์ selected_count ๋ฅผ +1 ํ๋ ์
๋ฐ์ดํธ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๋๋ฐ update ํ ๋์๋ ํด๋น ๋ ์ฝ๋์ ๋ฐฐํ๋ฝ์ ํ๋ํด์ผ ํฉ๋๋ค.
update appointment set selected_count=1 where id = 1;
select * from performance_schema.data_locks;
SQL
๋ณต์ฌ
์ผ์ชฝ์ ๊ณต์ ๋ฝ๊ณผ ๋๋ถ์ด, X ๋ผ๋ ๋ฐฐํ๋ฝ(eXclusive lock) ์ ํ๋ํ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ, ๊ณต์ ๋ฝ์ ์กฐํ๊ฐ ๊ฐ๋ฅํ์ง๋ง ์์ ์ ๋ถ๊ฐ๋ฅํ๊ณ , ๋ค๋ฅธ ํธ๋์ญ์
์์๋ ๋ฐฐํ๋ฝ ํ๋์ด ๋ถ๊ฐ๋ฅํ์ฌ ํ๋์ด ๊ฐ๋ฅํ ๋๊น์ง ๋๊ธฐํฉ๋๋ค. ๊ทธ๋์ ๋ง์ฝ ๋ ๊ฐ์ ํธ๋์ญ์
์์ ๊ฐ๊ฐ ๊ณต์ ๋ฝ์ ํ๋ ํ ๋ฐฐํ๋ฝ์ ํ๋ํ๋ ค๊ณ ์๋ํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ์๋ก ์ฝํ ์ํ์์ ๋ฐฐํ๋ฝ์ ํ๋ํ๋ ค๊ณ ์๋ํ๋ฉด ์๋ก ๋๊ธฐ๋ง ํ๋ ์ํ์ ๋น ์ ธ ๋ฐ๋๋ฝ์ด ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
์ด ๋ฐ๋๋ฝ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฌ๋ฌ๊ฐ์ง ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์๊ฐํด๋ณด์์ต๋๋ค.
๋น๊ด๋ฝ
๊ฐ์ฅ ๋จผ์ , ๊ตฌ์ํ๊ธฐ ๊ฐ์ฅ ์ฌ์ด ๋น๊ด์ ๋ฝ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํด ๋ณด์์ต๋๋ค.
1๋ฒ ๋ก์ง์ธ ์ฝ์์ก๊ธฐ ์กฐํ ์ ๋น๊ด์ ๋ฝ์ ๊ฑธ์ด์ฃผ๊ฒ ๋๋ฉด ํด๋น ๋ ์ฝ๋์ ๋ํด ๋ฐฐํ๋ฝ์ ์ป๊ฒ ๋ฉ๋๋ค. ๋๋ฌธ์ A ํธ๋์ญ์
์์ ๋น๊ด์ ๋ฝ์ผ๋ก ์ฝ์์ก๊ธฐ๋ฅผ ์กฐํํ๋ฉด, A ํธ๋์ญ์
์ด ๋๋ ๋ ๊น์ง ๋ค๋ฅธ ํธ๋์ญ์
๋ค์ ๋ฐฐํ๋ฝ ํ๋๋, ๊ณต์ ๋ฝ ํ๋๋ ๋ถ๊ฐ๋ฅํฉ๋๋ค(๋จ ๋ฝ ํ๋์๋ ๋จ์ ์กฐํ๋ ๊ฐ๋ฅํฉ๋๋ค). ํ๋ฒ์ ํ ํธ๋์ญ์
๋ง ๋ฝ์ ์ป์ ์ ์์ผ๋ฏ๋ก ์ ํฉ์ฑ ๋ฌธ์ ๋, ๋ฐ๋๋ฝ ๋ฌธ์ ๋ ํด๊ฒฐ๋ฉ๋๋ค.
์คํ๋ง์์๋ @Lock ์ด๋
ธํ
์ด์
์ ํตํด ๋น๊ด์ ๋ฝ๊ณผ ๋๊ด์ ๋ฝ์ ์ง์ํฉ๋๋ค.
@Query("select a from Appointment a where a.menu.code.code = :appointmentCode")
@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<Appointment> findByCodeForUpdate(@Param("appointmentCode") String appointmentCode);
Java
๋ณต์ฌ
๊ทธ๋ฆฌ๊ณ CountDownLatch ๋ฅผ ์ด์ฉํ์ฌ ์ฐ๋ ๋ 100๊ฐ๋ฅผ ๋ณ๋ ฌ์ ์ผ๋ก ์ํํ๋ ํ
์คํธ๋ฅผ ๋ง๋ค์ด ํ
์คํธ๋ฅผ ํด๋ณด์์ต๋๋ค.
๋น๊ด์ ๋ฝ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ์กฐํ ์์ for update ํค์๋๋ฅผ ํตํด ๋ฐฐํ๋ฝ์ ํ๋ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์๋ฃ๋ ๊ฐฏ์๋ฅผ ์ธ์ด๋ณด๋ฉด!
select selected_count, (select count(*) from appointment_available_time) as 'appointment_available_time_count' from appointment;
SQL
๋ณต์ฌ
100 ๊ฐ์ ๋ฐ์ดํฐ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์ฝ์
๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ๋จ, ์ด๋ ๊ฒ ํ ๊ฒฝ์ฐ ๋๊ธฐ ์๊ฐ์ด ํฌ๊ฒ ๋ฐ์ํฉ๋๋ค. ์์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ๋ก์ง์ ์์ํ์๋ง์ ํธ๋์ญ์
์์ ๋ฐฐํ๋ฝ์ ์ป๊ธฐ๋๋ฌธ์ ์ดํ์ ์ฐ๋ ๋์์๋ ๊ฐ๊ฐ์ ํธ๋์ญ์
๋ค์ด ๋จผ์ ์์๋ ํธ๋์ญ์
์์ ์ปค๋ฐ ๋๋ ๋กค๋ฐฑ๋ ๋๊น์ง ๋ก์ง์ ์คํํ์ง ๋ชปํ๊ณ ๋๊ธฐ ์ํ์ ๋น ์ง๊ฒ ๋ฉ๋๋ค. ์ ํฉ์ฑ์ ํ์คํ๊ฒ ๋ง์ถ ์๋ ์์ง๋ง, ๋์์ ์ ๊ทผํ๋ ํธ๋์ญ์
์ด ๋ง์์ง๋ฉด ๋ง์์ง์๋ก API ์ฝ์ ๋๊ธฐ ์๊ฐ์ ๋์ด๋๊ฒ ๋ฉ๋๋ค. ๋ํ ํ์
์์๋ ํจ์จ์, ๋น๊ด๋ฝ์ ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋๋ค๋ ์น๊ตฌ์ ๋ง์ ๋ค์ด ๋น๊ด์ ๋ฝ์ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ผ๋ก ๊ฒฐ์ ํ์์ต๋๋ค.
๋๊ด์ ๋ฝ์ ํ์ฌ ์ํ์์๋ ๋ฐ๋๋ฝ์ ๋น ์ง๋ ๊ฒ์ ํผํ ์ ์๊ธฐ๋๋ฌธ์ ์ดํ์ ๋ค๋ฃจ๋๋ก ํ๊ฒ ์ต๋๋ค.
foreign key ๋ผ๊ธฐ
๊ณต์ ๋ฝ์ ํ๋ํ๋ ์ด์ ๋ ์ธ๋ํค ์ ์ฝ ์กฐ๊ฑด ๋๋ฌธ์ด์์ต๋๋ค. ์ด์ ๋ฐ๋ผ ๋ฐ๋๋ฝ์ ์ ๋ฐ์์ผฐ๋ ๊ณต์ ๋ฝ ํ๋ํ๋ ๋ก์ง์ ์์ ๊ธฐ ์ํด ์ธ๋ํค ์ ์ฝ์กฐ๊ฑด์ ์ ๊ฑฐํ์์ต๋๋ค.
alter table appointment_available_time drop foreign key appointment_available_time_ibfk_1;
select * from information_schema.table_constraints where table_name = 'appointment_available_time';
SQL
๋ณต์ฌ
์ธ๋ํค ์ ์ฝ ์กฐ๊ฑด์ ์ ๊ฑฐํ ๋ค ๊ทธ๋๋ก ๋ก์ง์ ์ํํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
์ฝ์
๋ ๋ฐ์ดํฐ(appointment_available_time_count) ๋ 100๊ฐ์ธ๋ฐ, ์ค์ ๋ก ์
๋ฐ์ดํธ๋ ์ ํ ์ธ์(selected_count) ๋ 12๊ฐ์
๋๋ค. ๋ ๋ฐ์ดํฐ๊ฐ ๋ง์ง ์๋ ์ ํฉ์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์์ต๋๋ค.
์กฐํ ์์ ์๋ก ๋ค๋ฅธ ํธ๋์ญ์
์์ ๊ฐ์ count ๋ฅผ ์กฐํํ ๋ค, ๊ฐ๊ฐ ํธ๋์ญ์
์์ update ๋ฅผ ์ํํ๋ฉด ๋ค์ ์ํ๋ ํธ๋์ญ์
์ update ๊ฐ ์์ ํธ๋์ญ์
์์ update ํ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฎ์ด ์์ฐ๊ฒ ๋ฉ๋๋ค. ์ด๋ก ์ธํด ์์ ์ํ๋์๋ ํธ๋์ญ์
์ ๊ฒฐ๊ณผ๊ฐ ๋๋ฝ์ด ๋๊ณ ์ ํฉ์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฒ์
๋๋ค.
๋๊ด๋ฝ
๋น๊ด์ ๋ฝ์ ์์ ์ธ๊ธํ ์ํฉ๊ณผ ๊ฐ์ ๋น๊ด์ ๋ฝ ๋์ ๋๊ด์ ๋ฝ์ ์ฌ์ฉํด ๋ณด๊ธฐ๋ก ํ์์ต๋๋ค. ๋๊ด์ ๋ฝ์ version ์ปฌ๋ผ์ด ์กด์ฌํ๊ณ , update ์ ๊ธฐ์กด์ ์กฐํํ๋ version ๊ณผ ์ผ์นํ๋์ง ํ์ธ ํ update ํฉ๋๋ค. ๋ ์ฝ๋์ ๋ฐฐํ๋ฝ์ ๊ฑธ์ง ์๊ธฐ์ ์ฑ๋ฅ์ ํฌ๊ฒ ์ ํ๋์ง ์๊ณ ๋์์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ ๊ฒ์ด๋ผ๊ณ ํ๋จํ์์ต๋๋ค.
@Query("select a from Appointment a where a.menu.code.code = :code")
@Lock(LockModeType.OPTIMISTIC)
Optional<Appointment> findByCode(@Param("code") String code);
Java
๋ณต์ฌ
JPA ์์๋ ๋น๊ด์ ๋ฝ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก @Lock ์ด๋
ธํ
์ด์
์ ํตํด ๋๊ด์ ๋ฝ์ ์ง์ํฉ๋๋ค.
alter table appointment add column version int default 1;
SQL
๋ณต์ฌ
๊ทธ๋ฆฌ๊ณ ๋๋ฉ์ธ ๊ฐ์ฒด์ version ํ๋๋ฅผ ์ถ๊ฐํด์ค ๋ค ํด๋น ํ๋์ @Version ์ด๋
ธํ
์ด์
์ ๋ถ์ด๋ฉด ๋๊ด์ ๋ฝ์ ์ ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ํ
์คํธ๋ฅผ ๋๋ ค๋ณด๋ฉด!
update ํ ๋ ์์ ํ ๋ ์ฝ๋ ์ด์ธ์๋ version ์ด ์ผ์นํ๋์ง ํ์ธํ๊ธฐ ์ํด version ๋ ํจ๊ป ์กฐ๊ฑด์ ์ ์ถ๊ฐํ์ฌ ์กฐํํฉ๋๋ค. ํ์ง๋ง ํ
์คํธํ 100๊ฐ ๋ชจ๋ ์ ์ฉ๋์ง ์์ ํ
์คํธ์ ์คํจํ์์ต๋๋ค.
๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ์์ ์ ์คํจํ๋ฉด ๋กค๋ฐฑ์ ์งํํ์ฌ ์์ ์ฝ์
ํ ๋ฐ์ดํฐ๋ ๋ชจ๋ ์ทจ์๋๊ณ ๋กค๋ฐฑ๋ฉ๋๋ค. ๋๊ด์ ๋ฝ์ ์ ์ฉํ ๋ก์ง์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
์์ ํ ๊ฐ๊ณผ ์ฝ์
๋ ๊ฐ์ด ์ผ์นํ์ฌ ์ ํฉ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์๋ ์์์ต๋๋ค.
ํ์ง๋ง ๊ฒฐ๊ณผ์ ์ผ๋ก ์ ์ค๋ ๋ฐ์ดํฐ๊ฐ 87๊ฑด์ด ์์ต๋๋ค. ๋ฐ์ดํฐ ์ ์ค์ ํด๊ฒฐํ๊ธฐ ์ํด์๋ ๋น์ฆ๋์ค ๋ก์ง์์ rollback ์ด ๋ฐ์ํ๋์ง ํ์ธํ๊ณ ๋ค์ ๋์ผํ ๊ณผ์ ์ ์ํํ๋ while ๋ฐ๋ณต๋ฌธ์ ๋๋ ค์ผ ํฉ๋๋ค. ์ด ๋ฟ๋ง ์๋๋ผ ์ด๋ฏธ ๋๋ฉ์ธ ๊ฐ์ฒด์๋ ๋๊ด์ ๋ฝ๋ง์ ์ํ version ํ๋๊ฐ ์์ต๋๋ค. ์ ํฉ์ฑ๊ณผ ๋ฐ์ดํฐ ์ ์ค์๋ ๋๊ด์ ๋ฝ์ ๊ตฌํํ๊ธฐ ์ํด ๋น์ฆ๋์ค ๋ก์ง์ ํฌ์ํด์ผ ํ๋ ์ํฉ์ด ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค. ์ด๋ก ์ธํด ๋๊ด์ ๋ฝ์ ๋ณด๋ฅํ๊ธฐ๋ก ๊ฒฐ์ ํ์์ต๋๋ค.
๋ก์ง์ผ๋ก ํ๊ธฐ
๋ง์ง๋ง ๋ฐฉ๋ฒ์ count ๊ฐ์ ์์ ํ๋ ๋ํฐ ์ฒดํน์ ํฌ๊ธฐํ๊ณ ์ฟผ๋ฆฌ๋ฅผ ์ง์ ๋ ๋ฆฌ๋ ๋ฐฉ์์
๋๋ค.
๋น์ฆ๋์ค ๋ก์ง์์๋ count ๊ฐ์ ๋ณ๊ฒฝํ์ง ์๊ณ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ๋ง ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์์ ํ๋ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๋ฉด JPA ์์๋ flush ๋ฅผ ํ๊ณ ๋ํฐ ์ฒดํน์ ํตํด ๋ฐ์ดํฐ๊ฐ ์ถ๊ฐ๋๋ ์ฟผ๋ฆฌ๋ง ์์ฑํ ๋ค, ์์ ํ๋ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํฉ๋๋ค. ์์ ํ๋ ์ฟผ๋ฆฌ๋ ์์ ํ๋ ์์ ์ ๊ฐ์์ +1 ํ๋ ๋ก์ง์ด๊ธฐ๋๋ฌธ์ ์ ํฉ์ฑ์ ๋ง์ถ ์ ์์ต๋๋ค. ์ด๋ ์์ ์ธ๊ธ๋๋ฆฐ๋๋ก update ์ฟผ๋ฆฌ๋ฅผ ์คํํ ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฒด์ ์ผ๋ก ๋ฐฐํ๋ฝ์ ํ๋ํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด ๊ฒฝ์ฐ ๋ค๋ฅธ ๋ก์ง์ผ๋ก ์ธํ ๊ณต์ ๋ฝ์ ํ๋ํ์ง ์๊ธฐ์ ๋ฐ๋๋ฝ ๋ฌธ์ ๋ ํผํ ์ ์์ต๋๋ค.
@Modifying(clearAutomatically =true, flushAutomatically =true)
@Query("update Appointment a "
+ "set a.availableTimes.selectedCount = a.availableTimes.selectedCount + 1 "
+ "where a.menu.code.code = :appointmentCode")
void updateSelectedCount(@Param("appointmentCode") String appointmentCode);
Java
๋ณต์ฌ
ํ์ฌ ์ ์ฅ๋ ํ์์ ํ๋ก์ ์นด์ดํธ ๊ฐ์ +1์ ํด์ฃผ๋ JPQL์
๋๋ค. ๊ทธ๋ฆฌ๊ณ ํ
์คํธ๋ฅผ ๋๋ ค ๋ณด๋ฉด!
์ ํฉ์ฑ ๋ฌธ์ ์ ๋ฐ์ดํฐ ์ ์ค ๋ฌธ์ ๋ชจ๋ ํด๊ฒฐํ ์ ์์์ต๋๋ค.
์์ ์ฌ๋ฌ ๋ฐฉ๋ฒ๋ค๊ณผ ๋น๊ตํด๋ณด๋ฉด, JPA์ ๋ํฐ ์ฒดํน ๊ธฐ๋ฅ์ ํฌ๊ธฐํ์ฌ ๋ ๊ฐ์ฒด ์งํฅ์ ์ธ ์ฝ๋๊ฐ ๋๊ณ , ๋๋ฉ์ธ์ ๋ก์ง์ด ์๋น์ค ๊ณ์ธต์ผ๋ก ์ด๋ํด ๋น๋ํ ์๋น์ค ์ฝ๋๋ฅผ ๋ง๋๋ ๋จ์ ์ด ์์ต๋๋ค. ๋ํ JPQL ์ ์ ์ฉํ์ฌ ์๋์ผ๋ก ์์์ฑ ์ปจํ
์คํธ์ ๊ฐ์ฒด๋ฅผ flush ํ์ฌ ์ดํ ์์์ฑ ์ปจํ
์คํธ๋ฅผ ์ด์ฉํ๋ ค๋ฉด ๋ค์ ์กฐํ๋ฅผ ํด์ผ ํ๋ ๋ฑ ์์์ฑ ์ปจํ
์คํธ๋ฅผ ๋นํจ์จ์ ์ผ๋ก ์ด์ฉํ ์ ๋ฐ์ ์์ต๋๋ค. ํ์ง๋ง ๋ฝ์ ์ต์ํํ๋ฉด์ ์ ํฉ์ฑ์ ํ์คํ๊ฒ ๋ณด์ฅํ ์ ์๊ณ ๋ฐ์ดํฐ ์ ์ค ๋ฌธ์ ๋ ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด๊ธฐ๋ ํ๊ณ , ํด๋น ๋ก์ง ์ดํ์๋ ์์์ฑ ์ปจํ
์คํธ๋ฅผ ์ด์ฉํ๋ ๋ก์ง์ด ์๊ธฐ์ ์ ํฌ๋ ๋ก์ง์ผ๋ก ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์ ํํ์์ต๋๋ค.