Instagram Clone Coding #2 DB와 JPA
📝 요구사항
- 회원은 여러 개의 포스트를 작성할 수 있다.
- 회원은 다른 회원을 팔로우할 수 있다. (하나의 유저는 여러 명을 팔로우할 수 있고, 여러 명한테 팔로우 될 수 있다.)
- 하나의 포스트는 여러 개의 이미지를 가질 수 있다.
- 포스트에는 여러 개의 댓글이 달릴 수 있다.
- 포스트에 좋아요를 누를 수 있다.
- 댓글에는 대댓글이 달릴 수 있다.
- 댓글에는 좋아요를 누를 수 있다.
📏 ERD
위 내용을 바탕으로 dbdiagram.io를 사용해서 ERD를 작성했다.
✅ JPA
-
ORM(Object Relational Mapping : 객체 Object와 관계형 DB의 데이터를 자동으로 Mapping 해주는 것)의 일종
-
객체 지향적으로 프로그래밍을 하면, JPA가 이를 관계형 데이터베이스에 맞게 SQL을 대신 생성해서 실행함.
-
JPA는 인터페이스로 구현체가 필요함 - Hibernate, Eclipse Link 등, 하지만 Spring에서 JPA를 사용할 때는 이 구현체를 직접 다루지는 않고 Spring Data JPA라는 모듈을 이용함 (JPA <- Hibernate <- Spring Data JPA)
Hibernate 대신 Spring Data JPA를 쓰는 이유? -> 구현체 교체의 용이성 (Hibernate 외의 다른 구현체로 쉽게 교체), 저장소 교체의 용이성 (관계형 DB 이외의 다른 저장소로 쉽게 교체 - 예를 들어 MongoDB로 교체가 필요하다면 Spring Data JPA에서 Spring Data MongoDB로 의존성만 교체하면 된다)
🔍 적용하기
- build.gradle에 의존성 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // jpa 추가
runtimeOnly 'mysql:mysql-connector-java' // mysql
}
- Entity 클래스 생성
package com.clonecoding.instagrambackend.domain;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Getter
@EntityListeners(AuditingEntityListener.class)
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
private String text;
@CreatedDate
private LocalDateTime createdAt;
private Long views = 0L;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@OneToMany(mappedBy = "post", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Image> images;
@OneToMany(mappedBy = "post", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Comment> comments;
@OneToMany(mappedBy = "post", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<PostLike> likes;
public Post() {}
@Builder
public Post(String text, User user, List<Image> images) {
this.text = text;
this.user = user;
this.images = images;
}
}
DB 테이블의 column을 각각 변수로 지정한다.
@OneToMany, @ManyToOne 으로 연관 관계를 설정해줄 수 있다.
- JPA Repository 생성
Entity의 CRUD가 가능하도록 한다.
Entity 클래스와 함께 위치해야 한다.
package com.clonecoding.instagrambackend.domain;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
import java.util.Optional;
public interface PostRepository extends JpaRepository<Post, Long> {
List<Post> findByUser(User user);
@Query("SELECT count(c) from Post p join p.comments c where p.id = ?1")
Long countComments(Long id);
@Query("SELECT count(l) from Post p join p.likes l where p.id = ?1")
Long countLikes(Long id);
}
JpaRepository는 Dao 같은 DB Layer 접근자로 인터페이스로 생성한다. 단순히 인터페이스를 생성 후, JpaRepository<Entity 클래스, PK타입>을 상속하면 기본 CRUD 메서드가 자동으로 생성이 된다.
JpaRepository가 제공하지 않는 기능을 사용해야 할 때는 위에 @Query를 쓰면 원하는 쿼리를 지정해줄 수 있다.
Author And Source
이 문제에 관하여(Instagram Clone Coding #2 DB와 JPA), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@h000/Instagram-Clone-Coding-2-DB와-JPA저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)