๐Ÿค” JPA์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž

๊น€์„ฑ๊ธธยท2023๋…„ 4์›” 4์ผ
1

๊ธฐ์ˆ  ๋ฉด์ ‘ ์ค€๋น„

๋ชฉ๋ก ๋ณด๊ธฐ
3/7

JPA๋ž€?

JPA๋Š” Java Persistence API์˜ ์•ฝ์ž๋กœ ์ž๋ฐ” ORM ๊ธฐ์ˆ ์— ๋Œ€ํ•œ API ํ‘œ์ค€ ๋ช…์„ธ๋ฅผ ๋œปํ•œ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ ํŒจ๋Ÿฌ๋‹ค์ž„ ๋ถˆ์ผ์น˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์ฃผ๊ณ , ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์ œ๊ณตํ•ด์ค€๋‹ค.

ORM ์ด๋ž€?
Object Relational Mappaing์˜ ์•ฝ์ž๋กœ ๊ฐ์ฒด์™€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ๋งคํ•‘ํ•ด์ฃผ๋Š” ๊ธฐ์ˆ ์ด๋‹ค. ๊ฐ์ฒด๋Š” ๊ฐ์ฒด๋Œ€๋กœ, ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Œ€๋กœ ์„ค๊ณ„ํ•˜๊ณ , ORM ํ”„๋ ˆ์ž„ ์›Œํฌ๊ฐ€ ์ค‘๊ฐ„์—์„œ ๋งค์นญ์„ ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

JPA๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ์Œ์ด๋‹ค. ๋‹จ์ˆœํ•œ ๋ช…์„ธ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌํ˜„์ฒด๊ฐ€ ์—†๋‹ค. ๊ทผ๋ฐ ์šฐ๋ฆฌ๋Š” ์–ด๋–ป๊ฒŒ JPA๋ผ๋Š”๊ฑธ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„๊นŒ?

Hibernate

์šฐ๋ฆฌ๋Š” Hibernate๊ฐ€ JPA๋ฅผ ๊ตฌํ˜„ํ•œ ๊ตฌํ˜„์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์— JPA๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋Š”๊ฒƒ์ด๋‹ค!
๊ฐœ๋ฐœํ•œ์ง€ 10๋…„์ด ๋„˜์—ˆ๊ณ , ๋Œ€์ค‘์ ์œผ๋กœ ๋งŽ์ด ์ด์šฉํ•˜๋Š” ์œ ๋ช…ํ•œ JPA์˜ ๊ตฌํ˜„์ฒด ์ค‘ ํ•˜๋‚˜์ด๋‹ค.
Hibernamte๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ JDBC๋ฅผ ์ด์šฉํ•ด ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ปค๋„ฅ์…˜์„ ๋งบ๊ณ  ์ƒํ˜ธ์ž‘์šฉํ•œ๋‹ค.

JPA๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋‹ค๋ฅธ ๊ตฌํ˜„์ฒด๋“ค๋กœ๋Š” EclipseLink๋‚˜ DataNuclenus ๋“ฑ์ด ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

๋งŒ์•ฝ JPA๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ตฌํ˜„์ฒด๋“ค์ด ํ”„๋กœ์ ํŠธ์—์„œ ๋งž์ง€ ์•Š๊ฑฐ๋‚˜ ๋งˆ์Œ์— ๋“ค์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ JPA ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ

JPA๊ฐ€ ๋ญ”์ง€ ์•Œ์•˜์œผ๋‹ˆ JPA์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋Œ์•„๊ฐ€๋Š”์ง€ ์•Œ์•„๋ณด์ž. ๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์˜์†์„ฑ ๊ตฌ์กฐ์— ๋Œ€ํ•ด์„œ ์ดํ•ดํ•ด์•ผ ํ•œ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•˜๋ฉด EntityManagerFactory๋ฅผ ํ†ตํ•ด์„œ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ๋•Œ ๋งˆ๋‹ค EntityManager๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋˜ EntityManager๋ฅผ ํ†ตํ•ด์„œ ๋‚ด๋ถ€์ ์œผ๋กœ DB ์ปค๋„ฅ์…˜์„ ํ•ด DB๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š”๊ฒƒ์ด๋‹ค.

์œ„์— ์‚ฌ์ง„์„ ํ†ตํ•ด์„œ persist() ๋ฉ”์„œ๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋Œ์•„๊ฐ€๋Š”์ง€ ์•Œ์•„๋ณด์ž.

1. ๊ฐœ๋ฐœ์ž๊ฐ€ userRepository.save(userA) ์š”์ฒญ์„ ํ•œ๋‹ค.

๊ฐœ๋ฐœ์ž๊ฐ€ 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() ๋ฉ”์„œ๋“œ๋Š” ๋ง๊ทธ๋Œ€๋กœ ๋ณ‘ํ•ฉ ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

2. ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ์ง„์ž…

persist() ํ˜ธ์ถœ์‹œ userA๋ผ๋Š” ๊ฐ์ฒด๋Š” ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ์˜์—ญ์— ์ง„์ž…ํ•˜๊ฒŒ ๋œ๋‹ค. ์ด ์˜์—ญ์— ์ง„์ž…์‹œ Entity ๋‹จ์œ„๋กœ ๋ณ€ํ™˜๋˜์–ด ์ง„์ž…ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ์˜์—ญ์— ์ง„์ž…ํ•œ entity๋Š” key-value๋กœ 1์ฐจ ์บ์‹œ ๋ผ๋Š” ์˜์—ญ์— ๋˜ ์ €์žฅ๋œ๋‹ค. ์ด๋•Œ key๋Š” @Id ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํ•„๋“œ์ด๊ณ , value๋Š” entity๋กœ ์ €์žฅ๋œ๋‹ค.
๋˜ํ•œ ๋™์‹œ์— userA entity๋ฅผ DB์— ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ insert ์ฟผ๋ฆฌ๊ฐ€ ์“ฐ๊ธฐ์ง€์—ฐ SQL ์ €์žฅ์†Œ์— ์ €์žฅ๋œ๋‹ค.

3. ํŠธ๋žœ์ ์…˜ ์ปค๋ฐ‹์‹œ ์ฟผ๋ฆฌ๋ฌธ DB์— ์ „์†ก

JPA๋Š” ํ•œ ํŠธ๋žœ์žญ์…˜ ๋‹จ์œ„๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ DB์— ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•œ๋‹ค. ํŠธ๋žœ์žญ์…˜ ๋‹จ์œ„์— ์žˆ๋Š” ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•œ ํ›„ commit() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์“ฐ๊ธฐ์ง€์—ฐ SQL ์ €์žฅ์†Œ์— ์ €์žฅ๋˜์—ˆ์—ˆ๋˜ ๋ชจ๋“  ์ฟผ๋ฆฌ๋ฌธ์ด DB์— ๋‚ ๋ผ๊ฐ„๋‹ค.
์ผ์ฐจ์ ์œผ๋กœ๋Š” ๊ทธ๋ ‡๊ฒŒ ๋ณด์ผ ์ˆ˜๋„ ์žˆ์ง€๋งŒ commit() ๋ฉ”์„œ๋“œ๊ฐ€ flush() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ์ฟผ๋ฆฌ๋ฌธ์ด DB์— ๋‚ ๋ผ๊ฐ€๋Š”๊ฒƒ์ด๋‹ค.


Entity์˜ ์ƒ๋ช…์ฃผ๊ธฐ

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 ๊ฐ์ฒด๋ฅผ ์ง€์šฐ๊ฒ ๋‹ค๋Š” ์š”์ฒญ

๋ณ€๊ฒฝ ๊ฐ์ง€(Dirty Checking)

JPA๋Š” ์ˆ˜์ •๊ณผ ๊ด€๋ จ๋œ ๋ฉ”์†Œ๋“œ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋ณ€๊ฒฝ๊ฐ์ง€๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ • ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์œผ๋กœ์จ,
ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹์‹œ ์˜์†ํ™”๋œ entity์—์„œ ๊ฐ€์ง€๊ณ  ์žˆ๋˜ ์Šค๋ƒ…์ƒท(์ตœ์†Œ ์ •๋ณด)์™€ ๋ฐ”๋€ entity ์ •๋ณด๋ฅผ ๋น„๊ตํ•ด์„œ ๋ฐ”๋€ ๋ถ€๋ถ„์„ ์ˆ˜์ • ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

memberA.setNamge(10); // ์˜์† Entity ๋ฐ์ดํ„ฐ ์ˆ˜์ •
// => ๋”ํ‹ฐ ์ฒดํ‚น์œผ๋กœ ์ธํ•ด, persist() ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์•„๋„ ์ž๋™์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์ˆ˜์ •๋œ๋‹ค.

transaction.commit(); // ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹

์œ„ ์ฝ”๋“œ ์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์Šค๋ƒ…์ƒท๊ณผ ๋น„๊ตํ•ด ๋ฐ”๋€Œ๋ฉด update ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฐ๋‹ค.


๐Ÿ™‡โ€โ™‚๏ธ ์ถœ์ฒ˜ ๐Ÿ™‡โ€โ™‚๏ธ

https://velog.io/@msung99/JPA-Persist-Context-%EB%A5%BC-%ED%86%B5%ED%95%9C-%EC%98%81%EC%86%8D%EC%84%B1-Entity-%EA%B4%80%EB%A6%AC-%EB%A9%94%EC%BB%A4%EB%8B%88%EC%A6%98

https://bravenamme.github.io/2020/09/09/jpa_2/

0๊ฐœ์˜ ๋Œ“๊ธ€