JPA๋ Java Persistence API์ ์ฝ์๋ก ์๋ฐ ORM ๊ธฐ์ ์ ๋ํ API ํ์ค ๋ช ์ธ๋ฅผ ๋ปํ๋ค. ๋ํ์ ์ผ๋ก ํจ๋ฌ๋ค์ ๋ถ์ผ์น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ฃผ๊ณ , ์์์ฑ ์ปจํ ์คํธ๋ฅผ ์ ๊ณตํด์ค๋ค.
ORM ์ด๋?
Object Relational Mappaing์ ์ฝ์๋ก ๊ฐ์ฒด์ ๊ด๊ณํ ๋ฐ์ดํฐ ๋ฒ ์ด์ค๋ฅผ ๋งคํํด์ฃผ๋ ๊ธฐ์ ์ด๋ค. ๊ฐ์ฒด๋ ๊ฐ์ฒด๋๋ก, ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋๋ก ์ค๊ณํ๊ณ , ORM ํ๋ ์ ์ํฌ๊ฐ ์ค๊ฐ์์ ๋งค์นญ์ ํด์ฃผ๋ ์ญํ ์ ํ๋ค.
JPA๋ ์ธํฐํ์ด์ค์ ๋ชจ์์ด๋ค. ๋จ์ํ ๋ช ์ธ์ด๊ธฐ ๋๋ฌธ์ ๊ตฌํ์ฒด๊ฐ ์๋ค. ๊ทผ๋ฐ ์ฐ๋ฆฌ๋ ์ด๋ป๊ฒ JPA๋ผ๋๊ฑธ ์ฌ์ฉํ ์ ์์๊น?
์ฐ๋ฆฌ๋ Hibernate๊ฐ JPA๋ฅผ ๊ตฌํํ ๊ตฌํ์ฒด์ด๊ธฐ ๋๋ฌธ์ JPA๋ฅผ ์ธ ์ ์๋๊ฒ์ด๋ค!
๊ฐ๋ฐํ์ง 10๋
์ด ๋์๊ณ , ๋์ค์ ์ผ๋ก ๋ง์ด ์ด์ฉํ๋ ์ ๋ช
ํ JPA์ ๊ตฌํ์ฒด ์ค ํ๋์ด๋ค.
Hibernamte๋ ๋ด๋ถ์ ์ผ๋ก JDBC๋ฅผ ์ด์ฉํด ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ปค๋ฅ์
์ ๋งบ๊ณ ์ํธ์์ฉํ๋ค.
JPA๋ฅผ ๊ตฌํํ๋ ๋ค๋ฅธ ๊ตฌํ์ฒด๋ค๋ก๋ EclipseLink๋ DataNuclenus ๋ฑ์ด ์๋ค๊ณ ํ๋ค.
๋ง์ฝ JPA๋ฅผ ๊ตฌํํ๋ ๊ตฌํ์ฒด๋ค์ด ํ๋ก์ ํธ์์ ๋ง์ง ์๊ฑฐ๋ ๋ง์์ ๋ค์ง ์๋ ๊ฒฝ์ฐ ๊ฐ๋ฐ์๊ฐ ์ง์ JPA ๊ตฌํ์ฒด๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ค๊ณ ํ๋ค.
JPA๊ฐ ๋ญ์ง ์์์ผ๋ JPA์ ๋ด๋ถ ๊ตฌ์กฐ๊ฐ ์ด๋ป๊ฒ ๋์๊ฐ๋์ง ์์๋ณด์. ๊ทธ๋ฌ๊ธฐ ์ํด์๋ ์์์ฑ ๊ตฌ์กฐ์ ๋ํด์ ์ดํดํด์ผ ํ๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ๋ฉด EntityManagerFactory๋ฅผ ํตํด์ ํด๋ผ์ด์ธํธ ์์ฒญ์ด ๋ค์ด์ฌ๋ ๋ง๋ค EntityManager๋ฅผ ์์ฑํ๋ค. ๋ EntityManager๋ฅผ ํตํด์ ๋ด๋ถ์ ์ผ๋ก DB ์ปค๋ฅ์ ์ ํด DB๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋๊ฒ์ด๋ค.
์์ ์ฌ์ง์ ํตํด์ persist() ๋ฉ์๋๊ฐ ์ด๋ป๊ฒ ๋์๊ฐ๋์ง ์์๋ณด์.
๊ฐ๋ฐ์๊ฐ Entity๋ฅผ DB์ ์ ์ฅํ๊ธฐ ์ํด์ save ์์ฒญ์ ํ๋ฉด EntityManager๋ฅผ ํตํด persist()๋ฅผ ํธ์ถํ๊ฒ ๋๋ค.
SimpleJpaRepository.java
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
*/
@Transactional
@Override
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
์๋ํ๋ฉด ์์ save()
๋ฉ์๋๋ฅผ ๊น๋ณด๋ฉด ์๋ก์ด entity๋ผ๋ฉด persist()
๋ฉ์๋๋ฅผ ํธ์ถํ๊ฒ ๊ฐ๋ฐ์ด ๋์ด ์๊ธฐ ๋๋ฌธ์ด๋ค. ์๋ก์ด entity๊ฐ ์๋๋ผ๋ฉด merge()
๋ฉ์๋๋ฅผ ํธ์ถํ๋๋ฐ merge()
๋ฉ์๋๋ ๋ง๊ทธ๋๋ก ๋ณํฉ ํด์ฃผ๋ ์ญํ ์ ํ๋ค.
persist()
ํธ์ถ์ userA๋ผ๋ ๊ฐ์ฒด๋ ์์์ฑ ์ปจํ
์คํธ ์์ญ์ ์ง์
ํ๊ฒ ๋๋ค. ์ด ์์ญ์ ์ง์
์ Entity ๋จ์๋ก ๋ณํ๋์ด ์ง์
ํ๋ค. ์ด๋ ๊ฒ ์์์ฑ ์ปจํ
์คํธ ์์ญ์ ์ง์
ํ entity๋ key-value๋ก 1์ฐจ ์บ์ ๋ผ๋ ์์ญ์ ๋ ์ ์ฅ๋๋ค. ์ด๋ key๋ @Id ์ด๋
ธํ
์ด์
์ด ๋ถ์ ํ๋์ด๊ณ , value๋ entity๋ก ์ ์ฅ๋๋ค.
๋ํ ๋์์ userA entity๋ฅผ DB์ ์ ์ฅํ๊ธฐ ์ํ insert ์ฟผ๋ฆฌ๊ฐ ์ฐ๊ธฐ์ง์ฐ SQL ์ ์ฅ์์ ์ ์ฅ๋๋ค.
JPA๋ ํ ํธ๋์ญ์
๋จ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก DB์ ์์
์ ์ฒ๋ฆฌํ๋ค. ํธ๋์ญ์
๋จ์์ ์๋ ๋น์ง๋์ค ๋ก์ง์ ๋ชจ๋ ์ฒ๋ฆฌํ ํ commit() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์ฐ๊ธฐ์ง์ฐ SQL ์ ์ฅ์์ ์ ์ฅ๋์์๋ ๋ชจ๋ ์ฟผ๋ฆฌ๋ฌธ์ด DB์ ๋ ๋ผ๊ฐ๋ค.
์ผ์ฐจ์ ์ผ๋ก๋ ๊ทธ๋ ๊ฒ ๋ณด์ผ ์๋ ์์ง๋ง commit() ๋ฉ์๋๊ฐ flush() ๋ฉ์๋๋ฅผ ํธ์ถํด ์ฟผ๋ฆฌ๋ฌธ์ด DB์ ๋ ๋ผ๊ฐ๋๊ฒ์ด๋ค.
Entity์ ์๋ช ์ฃผ๊ธฐ๋ 4๊ฐ์ง๋ก ๋๋๋ค.
- ์์ ์ํ
- ๋น์์ ์ํ
- ์ค์์ ์ํ
- ์ญ์ ์ํ
User user = new User();
user.setId(1L);
user.setName("JPA!"); // ์ฌ๊ธฐ๊น์ง๋ ๋น์์ ์ํ
em.persist(user); // ์์ ์ํ (์์์ฑ ์ปจํ
์คํธ์ ์ํด ๊ด๋ฆฌ๋๋ค)
// => But, ์์ง DB ์ ์ ์ฅ๋์ง ์์๋ค. ์ฆ SQL ์ฟผ๋ฆฌ๊ฐ ์์ง ์๋ ๋ผ๊ฐ
em.detach(user); // ์ค์์ ์ํ
// => user ๋ฅผ ์์์ฑ ์ปจํ
์คํธ์์ ๋ถ๋ฆฌํ๋ค. Dirty Checking.. ๋ฑ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํ์ง ๋ชปํจ
em.remove(user); // ์ค์ DB์ ์๊ตฌ ์ ์ฅ๋ ์ํ์ธ user ๊ฐ์ฒด๋ฅผ ์ง์ฐ๊ฒ ๋ค๋ ์์ฒญ
JPA๋ ์์ ๊ณผ ๊ด๋ จ๋ ๋ฉ์๋๊ฐ ์กด์ฌํ์ง ์๋๋ค. ๋ณ๊ฒฝ๊ฐ์ง๋ ๋ฐ์ดํฐ๋ฅผ ์์ ํ ์ ์๊ฒ ํด์ฃผ๋ ๊ธฐ๋ฅ์ผ๋ก์จ,
ํธ๋์ญ์
์ปค๋ฐ์ ์์ํ๋ entity์์ ๊ฐ์ง๊ณ ์๋ ์ค๋
์ท(์ต์ ์ ๋ณด)์ ๋ฐ๋ entity ์ ๋ณด๋ฅผ ๋น๊ตํด์ ๋ฐ๋ ๋ถ๋ถ์ ์์ ํด์ฃผ๋ ๊ธฐ๋ฅ์ด๋ค.
memberA.setNamge(10); // ์์ Entity ๋ฐ์ดํฐ ์์
// => ๋ํฐ ์ฒดํน์ผ๋ก ์ธํด, persist() ๋ฅผ ํธ์ถํ์ง ์์๋ ์๋์ผ๋ก ๋ฐ์ดํฐ๊ฐ ์์ ๋๋ค.
transaction.commit(); // ํธ๋์ญ์
์ปค๋ฐ
์ ์ฝ๋ ์ฒ๋ผ ๋ฐ์ดํฐ๊ฐ ๋ฐ๋๋ฉด ์ค๋ ์ท๊ณผ ๋น๊ตํด ๋ฐ๋๋ฉด update ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฐ๋ค.