1. JDK 버전 업데이트 11 -> 17 & 의존성 업데이트 : JPA + MySQL +H2

JDK 버전 17로 업데이트. Spring Boot 에 DB 와 JPA 사용하게끔 의존성 추가.

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
  1. Spring Data JPA 속성과 설정

jpa auditing 기능을 쓰기 위해 JpaConfig` 추가.

application.properties 파일을 제거하고, application.yaml 파일 사용.

  1. 도메인 코드를 엔티티로 변환

1 도메인 클래스 == 1 테이블 매칭되도록 설계했다. 생성자와 equals(), hashcode() 등이 도메인 맥락에 맞게끔 디테일하게 설정함.

package com.example.projectboard.domain;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;

@Getter
@ToString
@Table(indexes = {
        @Index(columnList =  "title"),
        @Index(columnList = "hashtag"),
        @Index(columnList = "createdAt"),
        @Index(columnList = "createdBy")
})
@EntityListeners(AuditingEntityListener.class)
@Entity
public class Article {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;   // 제목
    private String content; // 본문
    private String hashtag; // 해시태그

    @Setter @Column(nullable = false) private String title;   // 제목
    @Setter @Column(nullable = false, length = 10000) private String content; // 본문

    @Setter private String hashtag; // 해시태그

    @OrderBy("id")
    @OneToMany(mappedBy = "article", cascade = CascadeType.ALL)
    @ToString.Exclude
    private final Set<ArticleComment> articleComments = new LinkedHashSet<>(); //중복을 허용하지 않음. 리스트로 볼 것.

    //meta data
    private LocalDateTime createdAt;    //생성일시
    private String createdBy;           //생성자
    private LocalDateTime modifiedAt;   //수정일시
    private String modifiedBy;          //수정자
    @CreatedDate @Column(nullable = false) private LocalDateTime createdAt;           //생성일시
    @CreatedBy @Column(nullable = false, length = 100) private String createdBy;      //생성자
    @LastModifiedDate @Column(nullable = false) private LocalDateTime modifiedAt;     //수정일시
    @LastModifiedBy @Column(nullable = false, length = 100) private String modifiedBy;//수정자

    protected Article() {
    }

    private Article(String title, String content, String hashtag) {
        this.title = title;
        this.content = content;
        this.hashtag = hashtag;
    }

    public static Article of(String title, String content, String hashtag) {
        return new Article(title,content,hashtag);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Article article)) return false;
        return id != null && id.equals(article.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}
package com.example.projectboard.domain;

import lombok.*;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.Objects;

@Getter
@ToString
@Table(indexes = {
        @Index(columnList =  "content"),
        @Index(columnList = "createdAt"),
        @Index(columnList = "createdBy")
})
@EntityListeners(AuditingEntityListener.class)
@Entity
public class ArticleComment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private Article article;    // 게시글 (ID)
    private String content;     // 본문

    @Setter @ManyToOne(optional = false) private Article article;    // 게시글 (ID)
    @Setter @Column(nullable = false, length = 500) private String content;     // 본문

    //meta data
    private LocalDateTime createdAt;    //생성일시
    private String createdBy;           //생성자
    private LocalDateTime modifiedAt;   //수정일시
    private String modifiedBy;          //수정자
    @CreatedDate @Column(nullable = false) private LocalDateTime createdAt;           //생성일시
    @CreatedBy @Column(nullable = false, length = 100) private String createdBy;                    //생성자
    @LastModifiedDate @Column(nullable = false) private LocalDateTime modifiedAt;     //수정일시
    @LastModifiedBy @Column(nullable = false, length = 100) private String modifiedBy;//수정자

    protected ArticleComment() {
    }

    private ArticleComment(Article article, String content) {
        this.article = article;
        this.content = content;
    }

    public static ArticleComment of(Article article, String content) {
        return new ArticleComment(article,content);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof ArticleComment that)) return false;
        return id != null && id.equals(that.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}