๐[03์ฅ] ์คํ๋ง ๋ถํธ์์ JPA๋ก DB ๋ค๋ฃจ๊ธฐ
- ํ๋ก์ ํธ์ Spring Data JPA ์ ์ฉํ๊ธฐ
- Spring Data JPA ํ ์คํธ ์ฝ๋ ์์ฑํ๊ธฐ
- ๋ฑ๋ก/์์ /์กฐํ API ๋ง๋ค๊ธฐ
- JPA Auditing์ผ๋ก ์์ฑ์๊ฐ/์์ ์๊ฐ ์๋ํํ๊ธฐ
๐ธJPA ์๊ฐ
- ๊ด๊ณํ DB๋ SQL๋ง ์ธ์ ๊ฐ๋ฅ. SQL์ ๋จ์ ๋ฐ๋ณต ์์ ๋ฌธ์
- ๋ฐ์ดํฐ ์ ์ฅ ๋ฐฉ๋ฒ์ ๋ฐ๋ผ ํจ๋ฌ๋ค์ ๋ถ์ผ์น ๋ฌธ์ ๋ฐ์
- ๊ด๊ณํ DB: ์ด๋ป๊ฒ ์ ์ฅํ ๊ฒ์ธ์ง์ ์ด์
- ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด: ๊ธฐ๋ฅ๊ณผ ์์ฑ์ ํ ๊ณณ์์ ๊ด๋ฆฌ
- ๊ฐ์ฒด์งํฅ์์ ๋ง๋ ๋ถ๋ชจ์ ์์ ๊ด๊ณ๊ฐ DB์์ ๊นจ์ง → ์์, 1:N ๋ฑ ๋ค์ํ ๊ฐ์ฒด ๋ชจ๋ธ๋ง์ DB์์ ๊ตฌํ ๋ถ๊ฐ → ๋ฐ์ดํฐ ๋ฒ ์ด์ค ๋ชจ๋ธ๋ง์๋ง ์ง์ค...
- JPA๊ฐ ๋ฌธ์ ํด๊ฒฐ : ํจ๋ฌ๋ค์ ์ผ์น์์ผ์ค
- ๊ฐ๋ฐ์ - ๊ฐ์ฒด์งํฅ์ ํ๋ก๊ทธ๋๋ฐ
- JPA: ์ด๋ฅผ ๊ด๊ณํ DB์ ๋ง๊ฒ SQL ๋์ ์์ฑ, ์คํ
- ๊ฐ์ฒด ์ค์ฌ ๊ฐ๋ฐ! ์์ฐ์ฑ ํฅ์, ์ ์ง๋ณด์์ ํธํจ
๐ธSpring Data JPA
- ์ธํฐํ์ด์ค์ธ JPA๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ๊ตฌํ์ฒด ํ์.
- JPA (์ธํฐํ์ด์ค)← Hibernate (๊ตฌํ์ฒด) ← Spring Data JPA (๋ชจ๋)
- Spring Data JPA๊ฐ ๋ฑ์ฅํ ์ด์
- ๊ตฌํ์ ๊ต์ฒด์ ์ฉ์ด์ฑ : Hibernate ์ธ์ ๋ค๋ฅธ ๊ตฌํ์ฒด(Eclipse Link ๋ฑ)๋ก ์ฝ๊ฒ ๊ต์ฒด ๊ฐ๋ฅ
- ์ ์ฅ์ ๊ต์ฒด์ ์ฉ์ด์ฑ : ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ธ์ ๋ค๋ฅธ ์ ์ฅ์ (MongoDB ๋ฑ)๋ก ์ฝ๊ฒ ๊ต์ฒด ๊ฐ๋ฅ
- Spring Data์ ํ์ ํ๋ก์ ํธ๋ค์ ๊ธฐ๋ณธ์ ์ธ CRUD ์ธํฐํ์ด์ค๊ฐ ๊ฐ์์ ์์กด์ฑ๋ง ๊ต์ฒดํ๋ฉด ๋จ
๐ธํ๋ก์ ํธ์ Spring Data JPA ์ ์ฉํ๊ธฐ
- build.gradle ์์กด์ฑ ๋ฑ๋ก
spring-boot-starter-data-jpa
- ์คํ๋ง ๋ถํธ์ฉ Spring Data JPA ์ถ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ.
์คํ๋ง ๋ถํธ ๋ฒ์ ์ ๋ง์ถฐ ์๋์ผ๋ก JPA ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ ๊ด๋ฆฌ h2
- ์ธ๋ฉ๋ชจ๋ฆฌ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค. ๋ณ๋์ ์ค์น ์์ด ํ๋ก์ ํธ ์์กด์ฑ๋ง์ผ๋ก ๊ด๋ฆฌ ๊ฐ๋ฅ.
๋ฉ๋ชจ๋ฆฌ์์๋ง ์คํ๋ผ์ ์ ํ๋ฆฌ์ผ์ด์ ์ฌ์์๋ง๋ค ์ด๊ธฐํ. → ํ ์คํธ ์ฉ๋๋ก ๋ง์ด ์ฌ์ฉ.
- ์คํ๋ง ๋ถํธ์ฉ Spring Data JPA ์ถ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ.
- domain ํจํค์ง ์์ฑ.
- ๋๋ฉ์ธ: ๊ฒ์๊ธ, ๋๊ธ, ํ์, ์ ์ฐ, ๊ฒฐ์ ๋ฑ ์ํํธ์จ์ด์ ๋ํ ์๊ตฌ์ฌํญ ํน์ ๋ฌธ์ ์์ญ
- domain ํจํค์ง์ posts ํจํค์ง์ Posts ํด๋์ค ์์ฑ
- Posts ํด๋์ค: ์ค์ DB์ ํ ์ด๋ธ๊ณผ ๋งค์นญ๋ ํด๋์ค. Entity ํด๋์ค๋ผ๊ณ ๋ ํจ.
- ๋ ์ค์ํ (์ฃผ์) ์ด๋
ธํ
์ด์
์ ํด๋์ค์ ๊ฐ๊น๊ฒ ๋๋ ๋ฐฐ์น
- → ์ฝํ๋ฆฐ ๋ฑ์ ์ ์ธ์ด ์ ํ์ผ๋ก ํ์ ์์ด์ง๋ฉด ๋ ์ค์ํ ์ด๋ ธํ ์ด์ ์ด ์์์ ์์ผ๋๊น ์ฝ๊ฒ ์ญ์ ๊ฐ๋ฅ
- ๋กฌ๋ณต ์ด๋ ธํ ์ด์ ์ ์๋น์ค ์ด๊ธฐ ๊ตฌ์ถ ๋จ๊ณ์์ ํ ์ด๋ธ ์ค๊ณ (์ฌ๊ธฐ์์ Entity ์ค๊ณ)๊ฐ ๋น๋ฒํ๊ฒ ๋ณ๊ฒฝ๋ ๋ ์ฝ๋ ๋ณ๊ฒฝ๋ ์ต์ํ
- PK๊ฐ์ Long type์ Auto_increment ์ถ์ฒ.
- ์ ๋ํฌ ํค(์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ ๋ฑ)๋ ๋ณตํฉํค(์ฌ๋ฌ ํค ์กฐํฉ)๋ก PK ์ก์ผ๋ฉด
- FK ๋งบ์ ๋ ๋ค๋ฅธ ํ ์ด๋ธ์์ ๋ณตํฉํค ์ ๋ถ๋ฅผ ๊ฐ๊ณ ์๊ฑฐ๋ ์ค๊ฐ ํ ์ด๋ธ ํ๋ ๋ ๋ฌ์ผํ๋ ์ํฉ ๋ฐ์
- ์ธ๋ฑ์ค์ ์ข์ ์ํฅX
- ์ ๋ํฌํ ์กฐ๊ฑด ๋ณ๊ฒฝ ์ PK ์ ์ฒด ์์ ํด์ผ ํ ์๋
- → ์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ, ๋ณตํฉํค ๋ฑ์ ์ ๋ํฌ ํค๋ก ๋ณ๋ ์ถ๊ฐ ์ถ์ฒ
- ์ ๋ํฌ ํค(์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ ๋ฑ)๋ ๋ณตํฉํค(์ฌ๋ฌ ํค ์กฐํฉ)๋ก PK ์ก์ผ๋ฉด
- Entity ํด๋์ค์์๋ ์ ๋ Setter ๋ฉ์๋๋ฅผ ์ฌ์ฉ X.
ํด๋น ํด๋์ค์ ์ธ์คํด์ค ๊ฐ๋ค์ด ์ธ์ ์ด๋์ ๋ณํด์ผ ํ๋์ง ์ฝ๋์ ๋ช ํ ๊ตฌ๋ถ ์ด๋ ต... ์ฐจํ ๊ธฐ๋ฅ ๋ณ๊ฒฝ ์ ๋ณต์กํด์ง.
→ ํ๋๊ฐ ๋ณ๊ฒฝ ํ์ํ๋ฉด ๋ชฉ์ ๊ณผ ์๋๋ฅผ ๋ํ๋ผ ์ ์๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉ- Setter ๋์ ์์ฑ์๋ฅผ ํตํด ์ต์ข
๊ฐ์ ์ฑ์ฐ๊ณ DB์ ์ฝ์
ํ๊ฑฐ๋ ํด๋น ์ด๋ฒคํธ์ ๋ง๋ public ๋ฉ์๋๋ฅผ ํธ์ถํด ๊ฐ ๋ณ๊ฒฝ
- ์ฌ๊ธฐ์ ์์ฑ์ ๋์ @Builder๋ฅผ ํตํด ์ ๊ณต๋๋ ๋น๋ ํด๋์ค ์ฌ์ฉ
(์์ฑ์ ๊ณตํต์ : ์์ฑ ์์ ์ ๊ฐ์ ์ฑ์์ฃผ๋ ์ญํ .
์์ฑ์์ ์ฐจ์ด์ : ์์ฐ์๋ ์ด๋ ํ๋์ ์ด๋ค ๊ฐ ์ฑ์์ผํ ์ง ๋ช ํ ์ง์ ๋ถ๊ฐ)
- ์ฌ๊ธฐ์ ์์ฑ์ ๋์ @Builder๋ฅผ ํตํด ์ ๊ณต๋๋ ๋น๋ ํด๋์ค ์ฌ์ฉ
- Setter ๋์ ์์ฑ์๋ฅผ ํตํด ์ต์ข
๊ฐ์ ์ฑ์ฐ๊ณ DB์ ์ฝ์
ํ๊ฑฐ๋ ํด๋น ์ด๋ฒคํธ์ ๋ง๋ public ๋ฉ์๋๋ฅผ ํธ์ถํด ๊ฐ ๋ณ๊ฒฝ
- JpaRepository ์ธํฐํ์ด์ค ์์ฑ : Posts ํด๋์ค๋ก DB์ ์ ๊ทผํ๊ฒ ํด์ค ์ธํฐํ์ด์ค. DB ๋ ์ด์ด ์ ๊ทผ์์.
- ์ธํฐํ์ด์ค ๋ง๋๋ ๊ฒ ์์ด์ ํค๋งธ๋๋ฐ new class ์์ฑํ๋ฉด interface ์ ํํ ์ ์๋ค..!!
- JpaRepository ์ธํฐํ์ด์ค ์ด๋ฆ์ PostRepository๋ก ์ง์ ํจ
- JpaRepository<Entity ํด๋์ค, PK ํ์ > ์์ → ๊ธฐ๋ณธ์ CRUD ๋ฉ์๋ ์๋ ์์ฑ
- Entity ํด๋์ค์ ๊ธฐ๋ณธ Entity Repository๋ ํจ๊ป ์์นํด์ผ ํ๋ฏ๋ก ๋๋ฉ์ธ ํจํค์ง์์ ํจ๊ป ๊ด๋ฆฌ
(๊ธฐ๋ณธ Repository ์์ผ๋ฉด Entity ํด๋์ค๋ ์ ์ญํ ๋ถ๊ฐ)
๐ธSpring Data JPA ํ ์คํธ ์ฝ๋ ์์ฑํ๊ธฐ
- Test์ domain ํจํค์ง์ posts ํจํค์ง, PostsRepositoryTest ํด๋์ค ์์ฑ
- ํ ์คํธ ์คํํด๋ณด๋ฉด ํต๊ณผํจ.
- ์ค์ ๋ก ์คํ๋ ์ฟผ๋ฆฌ๋ฅผ ๋ก๊ทธ๋ก ๋ณด๋ ค๋ฉด?
์ค์ ๋ก ์คํ๋ ์ฟผ๋ฆฌ๋ฅผ MySQL ๋ฒ์ ๋ก๊ทธ๋ก ๋ณด๋ ค๋ฉด?
// application.properties
spring.jpa.show_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
๐ธ๋ฑ๋ก/์์ /์กฐํ API ๋ง๋ค๊ธฐ
- API๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์ด 3๊ฐ์ ํด๋์ค๊ฐ ํ์
- Request ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ Dto
- API ์์ฒญ์ ๋ฐ์ Controller
- ํธ๋์ญ์
, ๋๋ฉ์ธ ๊ธฐ๋ฅ ๊ฐ์ ์์๋ฅผ ๋ณด์ฅํ๋ Service
- ๋น์ง๋์ค ๋ก์ง ์ฒ๋ฆฌ๋ Service์ ์ญํ ์ด X
- Spring ์น ๊ณ์ธต
- Web Layer
- ์ปจํธ๋กค๋ฌ(@Controller)์ JSP/Freemarker ๋ฑ์ ๋ทฐ ํ ํ๋ฆฟ ์์ญ
- ํํฐ(@Filter), ์ธํฐ์ ํฐ, ์ปจํธ๋กค๋ฌ ์ด๋๋ฐ์ด์ค(@ControllerAdvice) ๋ฑ ์ธ๋ถ ์์ฒญ๊ณผ ์๋ต์ ๋ํ ์ ๋ฐ์ ์ธ ์์ญ
- Service Layer
- @Service์ ์ฌ์ฉ๋๋ ์๋น์ค ์์ญ
- ์ผ๋ฐ์ ์ผ๋ก Controller์ Dao์ ์ค๊ฐ ์์ญ์์ ์ฌ์ฉ
- @Transactional์ด ์ฌ์ฉ๋ผ์ผ ํ๋ ์์ญ
- Repository Layer
- Database์ ๊ฐ์ด ๋ฐ์ดํฐ ์ ์ฅ์์ ์ ๊ทผํ๋ ์์ญ
- Dao (Data Access Object) ์์ญ
- Dtos
- Dto (Data Transfer Object)๋ ๊ณ์ธต ๊ฐ์ ๋ฐ์ดํฐ ๊ตํ์ ์ํ ๊ฐ์ฒด. Dtos๋ ์ด๋ค์ ์์ญ
- ex) ๋ทฐ ํ ํ๋ฆฟ ์์ง์์ ์ฌ์ฉ๋ ๊ฐ์ฒด๋ Repository Layer์์ ๊ฒฐ๊ณผ๋ก ๋๊ฒจ์ค ๊ฐ์ฒด ๋ฑ
- Domain Model
- ๋๋ฉ์ธ์ด๋ผ ๋ถ๋ฆฌ๋ ๊ฐ๋ฐ ๋์์ ๋ชจ๋ ์ฌ๋์ด ๋์ผํ ๊ด์ ์์ ์ดํดํ ์ ์๊ณ ๊ณต์ ํ ์ ์๋๋ก ๋จ์ํ์ํจ ๊ฒ
- ex) ํ์ ์ฑ) ๋ฐฐ์ฐจ, ํ์น, ์๊ธ ๋ฑ์ด ๋ชจ๋ ๋๋ฉ์ธ
- @Entity๊ฐ ์ฌ์ฉ๋ ์์ญ
- VO์ฒ๋ผ ๊ฐ ๊ฐ์ฒด๋ ๋๋ฉ์ธ ๋ชจ๋ธ์ ํด๋นํ๊ธฐ์ ๋ฌด์กฐ๊ฑด DB ํ ์ด๋ธ๊ณผ ๊ด๊ณ ์์ด์ผ ํ๋ ๊ฑด ์๋.
- Web, Service, Repository, Dto, Domain์ 5๊ฐ์ง ๋ ์ด์ด์์ ๋น์ฆ๋์ค ์ฒ๋ฆฌ๋ Domain์ด ๋ด๋น
- Web Layer
- service : ํธ๋์ญ์ , ๋๋ฉ์ธ ๊ฐ์ ์์๋ฅผ ๋ณด์ฅํ๋ ์์ญ
- ๋ฑ๋ก
- web/PostsApicontroller.java
- service/PostsService.java
@RequiredArgsConstructor
: ๋กฌ๋ณต ์ด๋ ธํ ์ด์ . final์ด ์ ์ธ๋ ๋ชจ๋ ํ๋๋ฅผ ์ธ์๊ฐ์ผ๋ก ํ๋ ์์ฑ์ ์์ฑ.
์์ฑ์๋ฅผ ์ง์ ์ ์ด ์ด์ : ํด๋น ํด๋์ค์ ์์กด์ฑ ๊ด๊ณ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์์ฑ์ ์ฝ๋๋ฅผ ๊ณ์ ์์ ํด์ผ ํ๋ ๋ฒ๊ฑฐ๋ก์ ํด๊ฒฐ ์ํด - web/dto/PostsSaveRequestDto.java
- Entity ํด๋์ค
- DB์ ๋ง๋ฟ์ ํต์ฌ ํด๋์ค.
- Entity ํด๋์ค๋ฅผ ๊ธฐ์ค์ผ๋ก ํ ์ด๋ธ ์์ฑ, ์คํค๋ง ๋ณ๊ฒฝ.
- ๋ณ๊ฒฝ๋๋ฉด ์ฌ๋ฌ ํด๋์ค์ ์ํฅ ๋ผ์นจ.
- ์ ๋ Request/Response ํด๋์ค๋ก ์ฌ์ฉํ๋ฉด ์ ๋จ.
→ Request/Response์ฉ Dto๋ View๋ฅผ ์ํ ํด๋์ค๋ผ ์ ๋ง ์์ฃผ ๋ณ๊ฒฝ ํ์.
View Layer์ DB Layer์ ์ญํ ๋ถ๋ฆฌ ์ฒ ์ ํ๊ฒ ํ๋ ๊ฒ ์ข์.
Controller์์ ๊ฒฐ๊ด๊ฐ์ผ๋ก ์ฌ๋ฌ ํ ์ด๋ธ์ ์กฐ์ธํด์ ์ค์ผ ํ ๊ฒฝ์ฐ๊ฐ ๋น๋ฒํ๋ฏ๋ก Entity ํด๋์ค๋ง์ผ๋ก ํํํ๊ธฐ ์ด๋ ค์ด ๊ฒฝ์ฐ๊ฐ ๋ง์.
Entity ํด๋์ค์ Controller์์ ์ธ Dto๋ ๋ถ๋ฆฌ ํ์.
- ํ
์คํธ - web/PostsApiControllerTest.java
- ์์
- web/PostsApiController
- web/dto/PostResponseDto
- service/posts/PostService
- ํ ์คํธ ์ฝ๋ ์คํ → update๋ ๊ฑฐ ํ์ธ ๊ฐ๋ฅ
- ์กฐํ
- resources/application.properties
main์์ Application.java ์ฝ๋ ์คํ ํ ์ฝ์์์ tomcat 8080 ์คํ๋ ๊ฑฐ ํ์ธ ํ
http://localhost:8080/h2-console๋ก ์ด๋
- resources/application.properties
โ๐ซTrouble Shooting!
tomcate 8080 ํฌํธ ์ด๋ฆฐ ๊ฑฐ ํ์ธ๋๋๋ฐ ํ์ด์ง ์ ์์ด ์ ๋๋ ๋ฌธ์
→ resources/application.properties๋ฅผ test ์์ ๋๋๋ฐ main ์์ resources/application.properties์ h2 ๊ด๋ จ ์์ฑ ์ ์ด์ค์ผํจ
๐ธJPA Auditing์ผ๋ก ์์ฑ์๊ฐ/์์ ์๊ฐ ์๋ํํ๊ธฐ
- entity์๋ ํด๋น ๋ฐ์ดํฐ์ ์์ฑ์๊ฐ, ์์ ์๊ฐ์ด ๋ณดํต ํฌํจ๋๋๋ฐ ๋ชจ๋ ํ ์ด๋ธ๊ณผ ์๋น์ค ๋ฉ์๋์ ๋จ์ํ๊ณ ๋ฐ๋ณต์ ์ธ ์ด ์ฝ๋๊ฐ ํฌํจ๋๋ ๊ฑธ ํด๊ฒฐํ๊ณ ์ JPA Auditing ์ฌ์ฉ
- domain/BaseTimeEntity.java
์ด BaseTimeEntity ํด๋์ค๋ ๋ชจ๋ Entity์ ์์ ํด๋์ค๊ฐ ๋์ด Entity๋ค์ createdDate, modifiedDate๋ฅผ ์๋ ๊ด๋ฆฌ - Posts ํด๋์ค๊ฐ BaseTimeEntity๋ฅผ ์์๋ฐ๋๋ก extends ์์ฑ
- public class Posts
extends BaseTimeEntity
- public class Posts
- JPA Auditing ์ด๋
ธํ
์ด์
๋ค์ ๋ชจ๋ ํ์ฑํ ๊ฐ๋ฅํ๊ฒ Application ํด๋์ค์ ํ์ฑํ ์ด๋
ธํ
์ด์
ํ๋ ์ถ๊ฐ
@EnableJpaAuditing
// JPA Auditing ํ์ฑํ
- ํ
์คํธ ์ฝ๋ ์์ฑ ํ ์คํ
- BaseTimeEntity๋ง ์์๋ฐ์ผ๋ฉด Entity์ ๋ฑ๋ก์ผ, ์์ ์ผ ์ด์๋ ์๋ ํด๊ฒฐ