Instagramクローンコード2 DBとJPA


📝 要求

  • 会員は複数の文章を書くことができます.
  • 会員は他の会員に注目することができます.△1人のプレイヤーは複数のユーザに注目してもよいし、複数のユーザに注目してもよい.
  • の文章には複数の画像があります.
  • ポストには複数のコメントがあります.
  • 後に「いいね」をクリックできます.
  • コメントには大きなコメントがあります.
  • コメントはいいですね.
  • 📏 ERD


    以上に基づき、ERDはdbdiagram.ioを用いて作成される.

    ✅ JPA


  • オブジェクト関係マッピング(ORM)

  • オブジェクト指向プログラミングの場合、JPAはSQLを作成して実行し、リレーショナル・データベースに一致させます.

  • JPAはインタフェース実装—Hibernate、Eclipse Linkなどを使用する必要があるが、SpringでJPAを使用する場合は、その実装をそのまま使用するのではなく、Spring Data JPAというモジュールを使用する(JPA<-Hibernate<-Spring Data JPA)
    なぜSpring Data JPAを使用してHibernateではないのですか->インプリメンテーションの交換が容易
  • 🔍 適用

  • build.gradeへの依存性
  • を追加
    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テーブルのカラムをそれぞれ変数として指定します.
    @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);
    }
    
    Jpa RepositoryはDaoのようなDB層アクセス者のインタフェースで生成される.インタフェースのみを作成し、Jpa Repositoryを継承すると、デフォルトのCRUDメソッドが自動的に作成されます.
    JpaRepositoryが提供しない機能を使用する必要がある場合は、@Queryと書いて必要なクエリーを指定できます.