๋ชฉ๋กJPA (9)
DevLog ๐ถ

๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ ๋๋ฌด ์ค๋๋ง์ ์์ฑํ๋ ๋ธ๋ก๊ทธ ๊ธ...! ์ต๊ทผ์ ์ฌ๋ด์์ ๋งค์ฐ ๋ง์ด ์ฐ์ด๋ ๋๋ฉ์ธ์ ๋ํด์ ๋ฆฌํฉํฐ๋ง์ ์งํํ์๋๋ฐ, ๊ฑฐ๊ธฐ์ ๋ง๋ฌ๋ ์ด์๋ค๊ณผ ๊ฐ๋จํ ์๊ฐ ๊ธฐ๋ก์ ๋ธ๋ก๊ทธ์ ๋จ๊ธฐ๋ฉด ์ข์ ๊ฒ ๊ฐ์์ ์์ฑํ๊ณ ์ ํ๋ค. ์ด๋ฏธ ํ ๋ด์์ ๊ณต์ ๋ ํ์๊ณ , ๋๊ธฐ๋ค์๊ฒ๋ ๊ณต์ ํ ๋ด์ฉ์ด๊ธฐ๋ ํ๊ณ , ์ฌ์ค ๋ณ๊ฑฐ ์๋ ๊ฑฐ๋ผ ๊ทธ๋ฅ ๊ฐ๋จํ๊ฒ๋ง ์ ๋ฆฌํ ์์ ์ด๋ค. ๐ฑ ๋ฌธ์ ์ํฉ๋ฆฌํฉํฐ๋ง์ ์งํํ๊ณ ์ ํ ๋๋ฉ์ธ์ ์ฐ๋ฆฌ ํ์์ ๋งค์ฐ ์ค์ํ ๋น์ฆ๋์ค ๋๋ฉ์ธ ๊ฐ์ฒด ์ค ํ๋์๊ณ , ์ด๋ฏธ ์์ ์ ์ผ๋ก ์ ์ด์๋๊ณ ์์ง๋ง ๊ต์ฅํ ์๋ ๋ถํฐ ๋ ๊ฑฐ์๋ก ๋ด๋ ค์ค๊ณ ์๋ ๊ฐ์ฒด์๊ธฐ ๋๋ฌธ์ ์ ๊ท ์ ์ฌ์๊ฐ ๋ณด๊ธฐ์ ์ข์ ์ฝ๋๊ฐ ์๋๋ผ๋ ์๊ฐ์ด ๋ค์๋ค. ์ฌ๋ด ๋๋ฉ์ธ์ธ ๋งํผ ๊ทธ๋๋ก ๊ฐ์ ธ์ฌ ์๋ ์์ง๋ง, ๋น์ทํ ๋๋์ผ๋ก ์๋์ ๊ฐ์ด ์ธํ ์ ์งํํด๋ณด์๋ค.CREAT..

๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ ์๋ ์ ์ผ๋ ๊ธ์ธ๋ฐ, ์์ฆ ๋ธ๋ก๊ทธ๋ฅผ ๋๋ฌด ์ ์ด ๊ฒ ๊ฐ์์ ์ค๋๋ง์ ์ฌ๋ฆฌ๋ ๊ธ ๐ถ ํผ์ ๊ณต๋ถํ ๊ฒธ ์์ฑํ ๊ธ์ด์์ด์ ๋ค์ ์ค๋ช ์ด ๋ถ์กฑํฉ๋๋ค...! ๐ฑ ์ํฐํฐ ์๊ฐ @Entity @EntityListeners(AuditingEntityListener.class) public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) @CreatedDate private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime updatedAt; User ํด๋์ค๋ ์ฌ์ฉ์์ ๋ํ ์ํฐํฐ์ด๋ฉฐ, id..

๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ ์ฐ๋ฆฌ ํ์ ๊ฒฝ์ฐ E2E ํ ์คํธ ํ๊ฒฝ์ ๊ตฌ์ถํ๊ธฐ ์ํด์ @SpringBootTest๋ฅผ ํตํด ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๊ณ ์๋๋ฐ, ์ฐ๋ฆฌ ํ์ ํ์๋ถ์ด ์๋์ ๊ฐ์ ์ค๋ฅ๋ฅผ ๋ง๋๊ฒ ๋์๋ค. failed to lazily initialize a collection of role: co.kirikiri.domain.roadmap.RoadmapContent.nodes.values: could not initialize proxy - no Session ์ํฉ์ ์๋์ ๊ฐ๋ค. (์ถํ ์ฝ๋๋ก ๋ ์ ์ดํด๋ณผ ์์ ์ด๋ค.) A๋ผ๋ ์์ฑ API์ B๋ผ๋ ์กฐํ API๊ฐ ์์ ๋, ํ ๋ด์์ ๊ธฐ๋ฅ์ ์ธ๋ถํํ ๋ค์ ๊ฐ์ ๊ฐ๋ฐ์ ์งํํ๋ค ๋ณด๋ B๋ฅผ ๊ฐ๋ฐํ๋ ์์ ์ A๋ผ๋ API๊ฐ ์์ด, ํตํฉ ํ ์คํธ ๋ repository๋ฅผ ..

๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ JPA์์ @OneToMany ๋จ๋ฐฉํฅ ๋งคํ๋ณด๋ค๋ ๋ค๋์ผ ์๋ฐฉํฅ ๋งคํ์ ๊ถ์ฅํ๋ค๋ ๋ง์ ๋ณด์์ ๊ฒ์ด๋ค. ํ์ง๋ง, ๊ฐ์ฒด์งํฅ์ผ๋ก ์ฝ๋๋ฅผ ์ค๊ณํ๋ค ๋ณด๋ฉด ๋ค๋์ผ์ ์ํฉ๋ณด๋ค๋ 1์ธ ์ํฐํฐ๋ฅผ ๊ธฐ์ค์ผ๋ก N์ธ ์ํฐํฐ๋ฅผ ์กฐํํ๋ ๊ฒฝ์ฐ๊ฐ ๋ ๋ง๊ณ , (์ ์ด๋ ๋ด ๊ฒฝํ์์๋ ๊ทธ๋ฌ๋ค) N์ธ ์ํฐํฐ๊ฐ ๊ตณ์ด 1์ธ ์ํฐํฐ์ ๋ํ ์ ๋ณด๋ฅผ ๋ชฐ๋ผ๋ ๋๋ ์ ์ด ๋ง์๋ค. ๊ทธ๋ฌ๋ค ๋ณด๋ ์์ฐ์ค๋ฝ๊ฒ ์ผ๋๋ค ๋จ๋ฐฉํฅ ๋งคํ์ ๋ง์ด ์ฌ์ฉํ์๋๋ฐ, ์ ๊ทธ๋ฌ๋ ๊ฒ์ธ์ง ๊ถ๊ธํด์ ๋๋ฆ๋๋ก ์คํ์ ํด๋ณด๊ณ ์ ํ๋ค. (ex. ๊ฒ์๊ธ๊ณผ ๊ฒ์๊ธ ์ด๋ฏธ์ง์ ๊ด๊ณ์์, ๊ฒ์๊ธ ์ด๋ฏธ์ง๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฒ์๊ธ ์ ๋ณด๋ฅผ ์ฐพ์์ค๋ ๊ฒ๋ณด๋ค๋ ๊ฒ์๊ธ์ ๊ธฐ์ค์ผ๋ก ๊ฒ์๊ธ ์ด๋ฏธ์ง ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ ๋ ๋ง์์) ๐ฑ ๊ธฐ๋ณธ ์ํฐํฐ ์ค๊ณํ๊ธฐ @Entity class Board( @Id @..

๐ฑ JPA ๊ธฐ๋ณธ ํค ์์ฑ ์ ๋ต JPA์์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ํค ์์ฑ ์ ๋ต์ ํฌ๊ฒ 5๊ฐ์ง๋ก ๋๋์ด์ง๋ค. - TABLE, SEQUENCE, IDENTITY, UUID, AUTO ๊ฐ ์ ๋ต์ ๋ํด์ ํ๋์ฉ ์์๋ณด๋๋ก ํ์. ๐ฑ TABLE ๐ก Indicates that the persistence provider must assign primary keys for the entity using an underlying database table to ensure uniqueness. - ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ์ฌ์ฉํ์ฌ ์ํฐํฐ์ ๊ธฐ๋ณธ ํค๋ฅผ ํ ๋นํด์ผ ํ๋ค. ๐ฌ ์ํฐํฐ ์ค์ @Entity class User( @Id @GeneratedValue(strategy = GenerationType.TABLE) val id: Lon..

๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ ์ง๋ ํฌ์คํ ์์๋ CascadeType.REMOVE์ ๋ํด์ ์ค์ ์ ์ผ๋ก ์์๋ดค์๋๋ฐ, ์ด๋ฒ์๋ orphanRemoval=true ์ต์ ์ ๋ํด์ ํ ๋ฒ ์์๋ณด์. ์ํฐํฐ ์ธํ ์ ์ง๋ ๋ฒ๊ณผ ๊ฑฐ์ ๋์ผํ๊ธฐ ๋๋ฌธ์ ๋ณํ๊ฐ ์๊ธด ๋ถ๋ถ์ ๋ํด์๋ง ๋ฐ๋ก ์ง๋๋ก ํ๊ฒ ๋ค. ๐ฑ ์ํฐํฐ ์์ ํ๊ธฐ ์ด๋ฒ์๋ CascadeType.REMOVE ๋์ ์ orphanRemoval=true๋ฅผ ์ ์ฉํ์. @Entity class Concert( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long = 0L, @Column(nullable = false) val name: String, @Column(nullable = false) val ticketLi..

๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ JPA๋ฅผ ๊ณต๋ถํ๋ฉด์ CascadeType.REMOVE์ orphanRemoval = true ์ต์ ์ ๋ํด์ ์ด๋ค ์ฐจ์ด๊ฐ ์๋์ง ์ ๋๋ก ์ธ์งํ ์ ์ด ์๋ ๊ฒ ๊ฐ์์, ์ด๋ฒ์ ๊ณต๋ถํ ๊ฒธ ์ฌ๋ฌ ๊ฐ์ง ํ ์คํธ๋ฅผ ์งํํด๋ณด๋ฉฐ ๋ ์ต์ ์ ์ฐจ์ด๋ฅผ ๊ณต๋ถํด๋ณด์๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๋งํ์๋ฉด Cascade ์ต์ ์ ๋ถ๋ชจ ์ํฐํฐ์ ์์ ์ํฐํฐ์ ์์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ์ด๊ณ , orphanRemoval์ ์กฐ๊ธ ๋ ์ธ๋ถ์ ์ผ๋ก ๊ณ ์ ๊ฐ์ฒด์ ๋ํ ๊ด๋ฆฌ๋ผ๋ ์๊ฐ์ด ๋ค์๋ค. ์ง๊ธ๋ถํฐ ์ฌ๋ฌ ์ผ์คํธ๋ฅผ ํ ์คํธํ๋ฉฐ ํ๋์ฉ ์์๋ณด์. ๐ฑ ์ํฐํฐ ์ธํ ํ๊ธฐ 1:N ๊ด๊ณ๋ฅผ ๋ด๋นํด์ค '์ฝ์ํธ' ์ํฐํฐ์ '์ฝ์ํธ ํฐ์ผ' ์ํฐํฐ๋ฅผ ์์ฑํ์๋ค. ๋ ์ฌ์ด์ ๊ด๊ณ๋ ์๋ฐฉํฅ์ผ๋ก ์ค์ ํ์์ผ๋ฉฐ, ํ๋์ ์ฝ์ํธ๋ ์ฌ๋ฌ ๊ฐ์ ์ฝ์ํธ ํฐ์ผ์ ๋ณด์ ํ ์ ์๋๋ก ์ค๊ณํ์..

๐ฑ ๋ฌธ์ ์ํฉ ํ์ด ํ๋ก๊ทธ๋๋ฐ์ ์งํํ๋ฉด์, ๋ถ๋ช ํ ์คํธ ์ฝ๋ ๊ฐ๊ฐ์ ์คํํ์ ๋๋ ์ ๋์๊ฐ๋๋ฐ ์ ์ฒด๋ฅผ ์คํํ๋๊น ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๋ฅผ ๋ง๋ฌ์๋ค. Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is ..

- ์ง๋ 9์์, ํ์ฌ์์ ์ฌ์ด๋ ํ๋ก์ ํธ๋ก JPA๋ฅผ ํ์ฉํ ๊ฒ์ํ ์๋น์ค ๊ฐ๋ฐ์ ์งํํ์๋๋ฐ, ์ฟผ๋ฆฌ ํ๋์ ์งํํ๋ค๊ฐ ๋ด ๋ง์๋๋ก ์ฟผ๋ฆฌ๊ฐ ๋๊ฐ์ง ์๋ ๊ฑธ ๋ณผ ์ ์์๋ค. - ๋น์ ๋ชจ๋ธ์ ๊ตฌ์กฐ๋ ๋๋ต์ ์ผ๋ก ์ด๋ ๋ค. ๊ธฐ๋ณธ์ ์ธ ๊ฒ์ํ ์ํฐํฐ์ด๋ค. @Table(name = "tb_board") @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Board extends BaseEntity { @Schema(description = "๊ฒ์๊ธ ๋ฒํธ", required = true) @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long boardNo; @S..