Instagram Clone Coding #2 DB와 JPA

HYΒ·2022λ…„ 3μ›” 24일
0

Instagram Clone Coding

λͺ©λ‘ 보기
3/3

πŸ“ μš”κ΅¬μ‚¬ν•­

  • νšŒμ›μ€ μ—¬λŸ¬ 개의 포슀트λ₯Ό μž‘μ„±ν•  수 μžˆλ‹€.
  • νšŒμ›μ€ λ‹€λ₯Έ νšŒμ›μ„ νŒ”λ‘œμš°ν•  수 μžˆλ‹€. (ν•˜λ‚˜μ˜ μœ μ €λŠ” μ—¬λŸ¬ λͺ…을 νŒ”λ‘œμš°ν•  수 있고, μ—¬λŸ¬ λͺ…ν•œν…Œ νŒ”λ‘œμš° 될 수 μžˆλ‹€.)
  • ν•˜λ‚˜μ˜ ν¬μŠ€νŠΈλŠ” μ—¬λŸ¬ 개의 이미지λ₯Ό κ°€μ§ˆ 수 μžˆλ‹€.
  • ν¬μŠ€νŠΈμ—λŠ” μ—¬λŸ¬ 개의 λŒ“κΈ€μ΄ 달릴 수 μžˆλ‹€.
  • ν¬μŠ€νŠΈμ— μ’‹μ•„μš”λ₯Ό λˆ„λ₯Ό 수 μžˆλ‹€.
  • λŒ“κΈ€μ—λŠ” λŒ€λŒ“κΈ€μ΄ 달릴 수 μžˆλ‹€.
  • λŒ“κΈ€μ—λŠ” μ’‹μ•„μš”λ₯Ό λˆ„λ₯Ό 수 μžˆλ‹€.

πŸ“ 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둜 μ˜μ‘΄μ„±λ§Œ κ΅μ²΄ν•˜λ©΄ λœλ‹€)

πŸ” μ μš©ν•˜κΈ°

  1. 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
}
  1. 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 으둜 μ—°κ΄€ 관계λ₯Ό 섀정해쀄 수 μžˆλ‹€.

  1. 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λ₯Ό μ“°λ©΄ μ›ν•˜λŠ” 쿼리λ₯Ό 지정해쀄 수 μžˆλ‹€.

0개의 λŒ“κΈ€