(์ ๊ถ๊ธ์ฆ ํ ์ฉ๋๋ก ์ ๋ฆฌํ๊ฑฐ๋ผ ๋ง ๊น๋ํ๊ฒ ์ ๋ฆฌํ์ง๋ ์์์ต๋๋ค.) ๐ง ManyToOne, OneToOne ์ฐ๊ด๊ด๊ณ ์ผ๋ฐ์ ์ผ๋ก merge ์ merge๋๋ ํน์ ์ํฐํฐ์ ๋ํด์๋ง ์กฐํํฉ๋๋ค. ๊ทธ๋ฌ๋ cascade ์์ฑ์ด MERGE๋ผ๋ฉด merge ์ ์ฐ๊ด๋ ์ํฐํฐ๋ค๋ left join์ผ๋ก ์กฐํํด์ต๋๋ค. merge()๊ฐ ๋์ด ๊ฐ์ด ๋ณ๊ฒฝ๋๋ ๊ฒ๋ ์ผ๋ฐ์ ์ผ๋ก๋ fk ๊ฐ์ ๋ณ๊ฒฝ๋ง์ด ๋ฐ์๋์ง๋ง, cascade ์์ฑ์ด merge๋ผ๋ฉด ์ฐ๊ด๋ ์ํฐํฐ์ ๋ณ๊ฒฝ๋ ํจ๊ป ๋ฐ์๋ฉ๋๋ค. (DB ๊ด์ ์์ ์๊ฐํ๋ฉด ํธํฉ๋๋ค) @NoArgsConstructor @Accessors(fluent = true) @Getter @Entity public class Member { @Id @GeneratedValue(strategy = Ge..
๐๏ธ Spring/JPA
๐ง ๋ฌธ์ ์ํฉ @Service @Transactional @RequiredArgsConstructor public class PostService { private final PostRepository postRepository; private final MemberRepository memberRepository; public Long create(CreatePostCommand command) { Member member = memberRepository.findById(command.memberId()) .orElseThrow(NotFoundMemberException::new); Post post = command.toPost(member); Post saved = postRepository.sa..
์ด ๋ฌธ์ ํด๊ฒฐํ๋ ค๊ณ ๊ฑฐ์ 5์๊ฐ๋์ ๋๋ฒ๊น
ํด์ ์์ธ ์ฐพ์๋๋๋ฐ, ์๊ณ ๋ณด๋๊น 1์ 26์ผ์ธ๊ฐ(๋ถ๊ณผ ํ๋ฌ ์ ) ํด๊ฒฐ๋์ด ์๋๋ผ๊ตฌ์.. ๋ค๋ง ์์ง ์คํ๋ง๋ถํธ jpa dependency ๋ฒ์ ์ ๋ฐ์์ด ์๋์ด์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค๋ ๊ฒ์ ๋ณด๊ณ ๊ทธ๋ฅ ์ฌํผํ๋ ์ค์
๋๋ค. ์๋ง ๊ณง ํด๊ฒฐ๋ ๊ฒ ๊ฐ์๋ฐ, ํด๋น ์ค๋ฅ๋ Hibernate 6.2 ์ด์ ๋ฒ์ ์์ ๋ฐ์ํฉ๋๋ค. ๐ง ๋ฌธ์ ์ํฉ ์ฌํ ์๋์ ๊ฐ์ด 1๋ ๋ค ์ฐ๊ด๊ด๊ณ๋ฅผ ๊ฐ์ง One๊ณผ Many๋ฅผ ์ ์ํ์์ต๋๋ค. @Entity public class One { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToMany(fetch = FetchType.LAZY, orphanRemoval =..
๐ง ์ฌ๋ฌ ์ปฌ๋ผ์ ๋ํ UNIQUE ์ ์ฝ์กฐ๊ฑด ์ค์ ํ๊ธฐ @Table์ uniqueConstraints ์์ฑ์ ์ฌ์ฉํ์ฌ ์ค์ ํ ์ ์์ต๋๋ค. ์ฌ์ฉ ์์ @Table( name="ํ
์ด๋ธ ์ด๋ฆ", uniqueConstraints={ @UniqueConstraint( name = "unique ์ ์ฝ์กฐ๊ฑด ์ด๋ฆ", columnNames = { "ํฌํจํ ์ปฌ๋ผ์ด๋ฆ 1", "ํฌํจํ ์ปฌ๋ผ์ด๋ฆ 2" } ), } columnNames๋ ํ๋๊ฐ ์๋ ์ปฌ๋ผ๋ช
๊ณผ ์ผ์นํด์ผ ํฉ๋๋ค. @Table( uniqueConstraints={ @UniqueConstraint( columnNames={"column1"}) } ) @Table( uniqueConstraints = { @UniqueConstraint(name = "UniqueNumber..
๐ง N + 1 ๋ฌธ์ N + 1 ๋ฌธ์ ๋ ์ฐ๊ด๊ด๊ณ๊ฐ ์ค์ ๋ ์ํฐํฐ ์ฌ์ด์์ ํ ์ํฐํฐ๋ฅผ ์กฐํํ์์ ๋, ์กฐํ๋ ์ํฐํฐ์ ๊ฐ์(N ๊ฐ)๋งํผ ์ฐ๊ด๋ ์ํฐํฐ๋ฅผ ์กฐํํ๊ธฐ ์ํด ์ถ๊ฐ์ ์ธ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ์๋ฏธํฉ๋๋ค. ์ฆ N + 1์์, 1์ ํ ์ํฐํฐ๋ฅผ ์กฐํํ๊ธฐ ์ํ ์ฟผ๋ฆฌ์ ๊ฐ์์ด๋ฉฐ, N์ ์กฐํ๋ ์ํฐํฐ์ ๊ฐ์๋งํผ ์ฐ๊ด๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๊ธฐ ์ํ ์ถ๊ฐ์ ์ธ ์ฟผ๋ฆฌ์ ๊ฐ์๋ฅผ ์๋ฏธํฉ๋๋ค. N + 1๋ณด๋ค๋, 1 + N์ด๋ผ ๋ถ๋ฅด๋ ๊ฒ์ด ๋ ์ดํดํ๊ธฐ ์ฌ์ฐ๋ฉฐ, ์ ๋ฆฌํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ์ํฐํฐ ์กฐํ ์ฟผ๋ฆฌ(1 ๋ฒ) + ์กฐํ๋ ์ํฐํฐ์ ๊ฐ์(N ๊ฐ)๋งํผ ์ฐ๊ด๋ ์ํฐํฐ๋ฅผ ์กฐํํ๊ธฐ ์ํ ์ถ๊ฐ ์ฟผ๋ฆฌ (N ๋ฒ) ๐ง ๋ฐ์ํ๋ ์ํฉ N + 1 ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ์ํฉ์ ์์๋ณด๊ธฐ ์ํด ๊ฒ์๊ธ๊ณผ ๋๊ธ์ ์์๋ก ์ฌ์ฉํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ํ๋์ ๊ฒ์..
๐ฅบ ์๋ก ๋๋ฉ์ธ ๊ณ์ธต์ Repository์ ์์์ฑ ๊ณ์ธต์ Repository๋ฅผ ๋ถ๋ฆฌํ์ฌ ์ฌ์ฉํด๋ณด๋ ค ์๋ํ๋ ๊ณผ์ ์์, findBy*** ์์ ์ด๋ฆ์ ๋ฉ์๋์, @Query๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ ๋ฑ์ ๋ฉ์๋๋ ์ด๋ค ์์ผ๋ก ์ฌ์ฉํด์ผ ํ๋์ง์ ๋ํด์ ์์๋ณด์๊ณ , ์ด๋ ค์ด ๋ด์ฉ์ ์๋๊ธฐ๋ ํ๊ณ ์๊ฐํ๋ ๋ฐฉ์ ๊ทธ๋๋ ์ ์ฉ๋๊ธด ํ์ง๋ง, ๊ทธ๋๋ ํน์ ๋์ ๋์๋ ๋ถ์ด ์์๊น๋ด ์์ฑํ๋ ค ํฉ๋๋ค. ๐ง ๋๋ฉ์ธ ๊ณ์ธต์ Repository์, ์์์ฑ ๊ณ์ธต์ Repository ๋ถ๋ฆฌํ๊ธฐ ์ ๋ ์ ์ฌ์ง์ฒ๋ผ ๋๋ฉ์ธ ๊ณ์ธต๊ณผ ์ธํ๋ผ์คํธ๋ญ์ณ ๊ณ์ธต์ ๋๋์๊ณ , JpaArticleRepository๋ ArticleRepository๋ฅผ ์์๋ฐ์ต๋๋ค. ArticleRepository๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ์์ต๋๋ค. ์ด๋ฅผ ์์๋ฐ์ Jp..
๊ธฐ์กด Auditing์ ์ฌ์ฉํ ๋์๋ ์๋์ ๊ฐ์ด ์ฌ์ฉํ์์ต๋๋ค. @EntityListeners(AuditingEntityListener.class) @MappedSuperclass public class BaseEntity { @CreatedDate @Column(updatable = false) private LocalDateTime createdDate; @LastModifiedDate private LocalDateTime lastModifiedDate; } ์์ ๊ฒฝ์ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์๋ ํญ์ 2022-03-06T14:12:23.0023123 ๊ณผ ๊ฐ์ ํ์์ผ๋ก ์ ์ฅ๋์๋๋ฐ, ์ด๋ฅผ ์ข ๋ ๊น๋ํ format์ผ๋ก ๋ฐ๊พธ๊ณ ์ถ์ ๋๊ฐ ์์ต๋๋ค. ๊ทธ๋ด ๋๋ @PrePersist, @PreUpdate๋ฅผ ์ฌ์ฉํ์ฌ..
(https://ttl-blog.tistory.com/807)ํด๋น ๊ธ์์ ์๋ก์ด ์ํฐํฐ๋ฅผ ๊ตฌ๋ณํ๋ ๋ฐฉ๋ฒ๊ณผ, save()์ ์๋ ์๋ฆฌ์ ๋ํ์ฌ ์์๋ณด์์ต๋๋ค. ๊ทธ๋ฌ๋ @GenerateValue๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์๋ณ์๋ฅผ ์ง์ ํ ๋นํ๋ ๊ฒฝ์ฐ์๋, ์ด๋ฏธ ์๋ณ์ ๊ฐ์ด ์๋ ์ํ๋ก save()๋ฅผ ํธ์ถํ๊ฒ ๋ฉ๋๋ค. ์ฆ ์ด ๊ฒฝ์ฐ์๋ merge()๊ฐ ํธ์ถ๋๋ ๊ฒ์
๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์๋ Persistable์ ์ฌ์ฉํ์ฌ ์๋ก์ด ์ํฐํฐ์ธ์ง ํ๋ณํ๋ ๋ฐฉ๋ฒ์ ์ง์ ๊ตฌํํ ์ ์์ต๋๋ค. Persistable์ ์๋ฆฌ Persistable์ ์์ ๊ฐ์ ์ธํฐํ์ด์ค์
๋๋ค. save ํธ์ถ ์์๋ SimpleJpaRepository์ save ๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํ๋์ด ์์ต๋๋ค. ์ด๋ entityInformation์ JpaE..