[Spring] JPA์ ํ๋ฌ์(flush)
JPA๋ฅผ ์ฌ์ฉํ ๋, ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ ์์์ฑ ์ปจํ ์คํธ์ ์์์์ผ ์ปค๋ฐํ๋ ๊ณผ์ ๊น์ง๋ฅผ ์์๋ดค์ต๋๋ค. ๊ทธ๋ฐ๋ฐ, JPA์ commit()์ ํธ์ถํ ๋ ํญ์ ๋ฐ์ํ๋ flush()๋ ์ด๋ค ์ญํ ์ ํ๋ ๋ ์์ผ๊น์?
flush()
์ปค๋ฐ ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฒ ๋๋ฉด JPA ์์์ฑ ์ปจํ ์คํธ์ ์๋ ๊ฐ์ฒด๋ค์ด DB๋ก ๋ฐ์๋๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ค์ ๋ก commit() ๋ฉ์๋๋ฅผ ํธ์ถํ์ ๋ ์ด๊ฒ์ด ์งํ๋๋ ๊ฒ์ผ๊น์? ์ฌ์ค์ commit() ๋ฉ์๋๊ฐ ํธ์ถ๋ ๋ flush() ๋ฉ์๋๊ฐ ํธ์ถ๋์ด์ง๊ณ , ์ค์ ๋ก๋ flush() ๋ฉ์๋์ ์ํด์ DB์ ๋ฐ์๋์ด์ง๋๋ค.
์ฆ, flush๋ ์์์ฑ ์ปจํ ์คํธ์ ๋ด์ฉ์ DB์ ๋ฐ์ํ๋ ์ญํ ์ ํ๋ ๋ฉ์๋์ด๋ฉฐ, ์ฐ๊ธฐ ์ง์ฐ SQL ์ ์ฅ์์ ์๋ SQL ์ฟผ๋ฆฌ๊ฐ DB ์๋ฒ๋ก ๋ณด๋ด์ง๊ธฐ ๋๋ฌธ์ ์์์ฑ ์ปจํ ์คํธ๋ ๊ทธ๋๋ก ๋จ์ ์๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ผ์ ๋ฐ๋์ ๊ฐ์ฒด๋ณ๋ก ์ค์์(detached)์ํ๋ก ์ ํํด์ค์ผ ํฉ๋๋ค.
// EntityManager ์์ฑ
EntityManager em = emf.createEntityManager();
// ์์ Entity ์กฐํ
Cafe cafe = em.find(Cafe.class, 1);
// ์์ Entity ์์
cafe.setName("iceAmericano");
// ์ด ๋, DB ์๋ฒ๋ก Query ์ ์ก
em.flush();
์ดํ, commit() ๋ฉ์๋๊ฐ ํธ์ถ๋์์ ๋๋ DB์ ์์์ฑ ์ปจํ ์คํธ๋ค์ด ๋ชจ๋ ์ ์ฅ๋์์์ด ํ์ ๋์ด์ง๊ฒ ๋๋ฏ๋ก ์ด ๋๋ถํฐ๋ ์์์ฑ ์ปจํ ์คํธ์ ๋ด์ฉ๊ณผ 1์ฐจ ์บ์์ ์๋ ๊ฐ์ฒด๋ค์ด ๋ชจ๋ ์ ๊ฑฐ๋ฉ๋๋ค.
flush() ๋์ ๊ณผ์
commit์ DB์ Transaction commit ์ฒ๋ผ DB์ ๋ณ๊ฒฝ ์ฌํญ ๋ฐ์์ ํ์ ์ง์์ ๋ ๋ํ๋ด๋ ๋ฉ์๋์๊ณ , ์ค์ ์ฟผ๋ฆฌ๋ฅผ ์ ์กํ๋ ๋ฉ์๋๋ ๋ณ๊ฐ๋ก ์กด์ฌํ๋ค๋ ๊ฒ์ ์์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด flush ๋ฉ์๋๋ ์ด๋ค์์ผ๋ก ๋์ํ๋ ๊ฑธ๊น์?
- ๋ณ๊ฒฝ์ ๊ฐ์งํ๋ค. (Dirty Checking)
- ์์ ๋ Entity๋ฅผ ์ฐ๊ธฐ ์ง์ฐ SQL ์ ์ฅ์์ ๋ฑ๋กํ๋ค.
- ์ฐ๊ธฐ ์ง์ฐ SQL ์ ์ฅ์์ Query๋ฅผ DB์ ์ ์กํ๋ค. (INSERT, UPDATE, DELETE ๋ฑ์ DML)
- flush() ๋ฉ์๋ ํธ์ถ ํ, commit() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
๋ค์ ํ ๋ฒ ๋ณต์ตํ๋ค๋ฉด, SELECT ์ฟผ๋ฆฌ์ ๊ฐ์ ์กฐํ ์ฟผ๋ฆฌ๋ EntityManager์์ ๋ฐ๋ก ์กฐํํ๊ณ , ์์ ์ด๋ ์ถ๊ฐ ์ฌํญ์ ๋ํด์๋ง ์์์ฑ ์ปจํ ์คํธ์ ๋ฃ๊ณ , ๋ณ๊ฒฝ ์ฌํญ์ ์ฐ๊ธฐ ์ง์ฐ SQL ์ ์ฅ์์ ๋ฃ์๋ค๊ฐ DB์ ๋ฐ์ํ๋ ๋ฐฉ์์ด๋ ์ ์ ์์๋ก์๋ค.์ด๋ฌํ flush ๋ฉ์๋๊ฐ ๋์ํ ์ ์๋ ์ด์ ๋ DB Transaction์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค. DB๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ธ ๋ ์์ ๋จ์(Transaction)๋ฅผ ๋๊ณ ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ํด๋น Transaction์ ๋์ (commit) ์ง์ ์๋ง ๋๊ธฐํ๋ฅผ ํด์ฃผ๋ฉด ๋๋ฏ๋ก ์ค๊ฐ ํจ์ ํธ์ถ์ด ๊ฐ๋ฅํ ๊ฒ์ ๋๋ค. JPA์์ ๋ฐ์ดํฐ์ ์ฑํฌ๋ ๋์์ฑ์ ๊ด๋ จ๋ ๊ฒ์ ์ ํ๋ฆฌ์ผ์ด์ ๋ ๋ฒจ์ด ์๋ DB์ Transaction์ ์์ํ๊ฒ ๋๋ฏ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ๋๋ ์ด๋ฌํ ์ด์๋ ์ ๊ฒฝ์ฐ์ง ์์ผ์ ๋ ๋ฉ๋๋ค.
flush()๋ ์ธ์ ํธ์ถ๋ ๊น?
JPA์์ flush ๋ฉ์๋๊ฐ commit() ์์ ์ ํธ์ถ๋๋ค๋ผ๊ณ ํ๋ค๋ฉด, ๊ฐ๋ฐ์๊ฐ ๊ตณ์ด flush()๋ฅผ ๊ฐ์ ๋ก ํธ์ถํด์ผ ๋ ๋๋ ์ธ์ ์ผ๊น์? ๋๋ฒ๊น ํ๊ฑฐ๋ ์ ๋ง๋ก commit ์ง์ ์, ๋ณ๊ฒฝ ์ฌํญ์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋์๋์ง ํ์ธํ๊ธฐ ์ํต์ ๊ฐ์ ํธ์ถ์ด ๋์ด์ผ ํ๋ค๋ฉด, ์ฐ๋ฆฌ๊ฐ flush()๊ฐ ํธ์ถ๋๋ ์์ ์ด ์ธ์ ์ธ์ง๋ ์์์ผ๊ฒ ์ฃ ?
- Transaction commit์ ํธ์ถ
- JPQL ์ฟผ๋ฆฌ ์คํ์ ํธ์ถ
๋ณดํต JPA๋ฅผ ๊ธฐ๋ณธ ์ต์ ์ผ๋ก ์ฌ์ฉํ๊ฒ ๋๋ฉด ์์ ๊ฐ์ด commit ํ ๋์ JPQL ์ฟผ๋ฆฌ๋ฅผ ์คํํ ๋, flush ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฒ ๋ฉ๋๋ค. JPQL์ด๋ Java Persistence Query Language์ ์ฝ์๋ก Java์์ ์ฌ์ฉํ ์ ์๋ ๊ฐ์ฒด ์งํฅ ์ฟผ๋ฆฌ ์ธ์ด์ ๋๋ค. Java์ ๋ง์ถฐ SQL ์ฟผ๋ฆฌ๋ฅผ ์ถ์ํ ํ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ DB์ ์ฐ๋๋์ง๋ง ์ ํ๋ฆฌ์ผ์ด์ ๋ ๋ฒจ์๋ง ์๋ค๊ฐ DB์์๋ ๋ค์ SQL๋ก ๋ฐ๋๊ฒ ๋๋ ์๋ฆฌ์ ๋๋ค.
// EntityManager ์์ฑ
EntityManager em = emf.createEntityManager();
// ์ค๊ฐ์ Query ์กฐํ
query = em.createQuery("select c from Cafe c", Cafe.class);
List<Cafe> cafeMenus = query.getResultList();
Spring Data JPA์์๋ @Query ์ด๋ ธํ ์ด์ ์ ์ด์ฉํ์ฌ JPQL์ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์ผ๋ฐ JPA์์๋ EntityManager ๊ฐ์ฒด๋ฅผ ์ด์ฉํ์ฌ createQuery ๋ฉ์๋๋ฅผ ์ด์ฉํ๋ฉด JPQL์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด ๋๋ DDL์ด๋ DML์ด๋ Query๋ฅผ ์คํํ๊ธฐ ์ , ์๋์ผ๋ก flush ๋ฉ์๋๊ฐ ํธ์ถ๋ฉ๋๋ค.
์ ์๋์ผ๋ก ๋ฐ์ํ๋ ๊ฑธ๊น์? ๊ทธ๊ฒ์ EntityManager์ ๊ธฐ๋ณธ flush ์ต์ ์ด FlushModeType.AUTO๋ก ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
em.setFlushMode(FlushModeType.COMMIT);
๋ง์ฝ, ์ปค๋ฐํ ๋๋ง flush ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฒ ํ๊ณ ์ถ๋ค๋ฉด, ์์ ๊ฐ์ด EntityManager ๊ฐ์ฒด์ flushMode ํ์ ์ COMMIT์ผ๋ก ์ค์ ํด์ฃผ๋ฉด ๋ค์๋ถํฐ JPQL์ ์ฌ์ฉํ ๋ flush ๋ฉ์๋๋ฅผ ํธ์ถํ์ง ์์ต๋๋ค.
JPQL์ ์ฌ์ฉํ์ ๋, flush ๋ฉ์๋๊ฐ ํ์ํ ๊ฒฝ์ฐ๋ ์ธ์ ์ผ๊น์? ๋ฐ๋ก ์์์ฑ ์ปจํ ์คํธ์ ์๋ ํ ์ด๋ธ์ ์กฐํํ ๋๋ flush ๋ฉ์๋๊ฐ ํ์ํฉ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ์๋ ๋๋ฉ์ธ์ ์๋ ํ ์ด๋ธ์ ์กฐํํด์ผ ํ ๊ฒฝ์ฐ, ์์ ์ํ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์กฐํํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๋ฐ๋ผ์ ์ด ๋๋ JPQL์ ์ฌ์ฉํด์ผ ํ๋๋ฐ, flush ๋ฉ์๋๋ฅผ ํตํด์ ๋๊ธฐํ ํ๋ค๋ฉด, JPA์ ์ด์ ์ ๊ทธ๋๋ก ์ด๋ฆด ์ ์๋ ์ฅ์ ์ด ์์ฃ .
๋ง์น๋ฉฐ...
์ฌ๊ธฐ๊น์ง ๊ฐ๋จํ๊ฒ flush ๋ฉ์๋์ ๋ํด์ ์์๋ดค์ต๋๋ค. ์ฌํ๊น์ง commit ๋ฉ์๋๋ฅผ ํธ์ถํด์ DB์ ๋ฐ์๋์๋ค๊ณ ์๊ฐํ๋๋ฐ, flush ๋ฉ์๋๋ฅผ ๋ณด๊ฒ ๋๋ฉด์ JPA๊ฐ DB์ ์ ํํ๊ฒ ๋๊ธฐํ ํ ์ ์๋ ๋งค์ปค๋์ฆ์ ๋์ ๋ฐฉ์์ ์๊ฒ ๋ ๊ณ๊ธฐ๊ฐ ๋์์ต๋๋ค.