본문 바로가기
프로그래밍/Java

[Springboot(스프링부터)]Entity생성과 JPA설정

by Mr.noobiest 2022. 7. 26.

Article.java의 있는 도메인들을 DB와 연동 가능하게 Entity

화 해주는 방법이다.

추가로 이후 검색이 가능하게 Index를 자동 생성 + JPA Auditing설정을 추가하여 일부러 내가 설정할 필요가 없는것들(ex)생성일시/생성자/수정일시 들을 자동으로 생성하게 해주는 기능도 추가한다.

package com.board.boardproject.domain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

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

@Getter
@ToString
@Table(indexes = {
        @Index(columnList = "title"),
        @Index(columnList = "hashtag"),
        @Index(columnList = "createdAt"),
        @Index(columnList = "createdBy")
})  //검색 가능하게 Index 설정
@Entity
public class Article {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; //내가 설정하는게 아니라 ID생성시 자동으로 값 부여

    //왜 Setter를 한꺼번에 안하고 일부러 나누냐면 id와 같이 민감한 정보는 변경되면 안되므로 별도로 지정하는것이다.
    @Setter private String title;
    @Setter private String content;
    @Setter private String hashtag;


    //JPA Auditing 자동 세팅하는 기능이 제공되어있음
    //com.board.boardproject하위에 config package생성 -> JpaConfig(Jpa설정 class파일 생성)
    private LocalDateTime  createdAt;
    private String  createdBy;
    private LocalDateTime modifiedAt;
    private String modifiedBy;
}

 

 

이후 JPA Auditing을 구현하기 위하여 com.board.boardproject폴더 하위에 config(package) 생성 -> JpaConfig.class를 생성하여 아래와 같이 설정해준다.

 

package com.board.boardproject.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;


@EnableJpaAuditing
@Configuration
public class JpaConfig {
}

 

이후 Article.java로 돌아와서 JPA Auditing을 구현하는데, 문제가 있다. CreatedData나 LastModifiedDate의 경우 컴퓨터내의 날짜/시간을 기준으로 쓰면 된다고 해도 / By와 같이 누가 수정 / 생성했는지에 대한 정보는 컴퓨터 상에 저장되어 있지 않고 보안에도 문제가 된다.

 

 

@Entity
public class Article {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; //내가 설정하는게 아니라 ID생성시 자동으로 값 부여

    //왜 Setter를 한꺼번에 안하고 일부러 나누냐면 id와 같이 민감한 정보는 변경되면 안되므로 별도로 지정하는것이다.
    @Setter private String title;
    @Setter private String content;
    @Setter private String hashtag;


    //JPA Auditing 자동 세팅하는 기능이 제공되어있음
    //com.board.boardproject하위에 config package생성 -> JpaConfig(Jpa설정 class파일 생성)
    @CreatedDate private LocalDateTime  createdAt;
    @CreatedBy private String  createdBy;
    @LastModifiedDate private LocalDateTime modifiedAt;
    @LastModifiedBy private String modifiedBy;
}

 

 

이를 방지하기 위하여 JpaConfig.java내에 해당 값들을 어떤걸 입력할건지 설정해주는것이다.

@EnableJpaAuditing
@Configuration
public class JpaConfig {

    @Bean
    public AuditorAware<String> auditorAware(){
        return() -> Optional.of("temp_Name");
    }
}

 

이렇게 하면 누가 입력을 하든 temp_Name으로 저장이 될것이다 ,물론 해당 부분("temp_Name")은  추후수정을 통해 실정 입력/수정자의 데이터가 입력될 것이다.

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

이후 각 도메인(Entity)의 최대 길이  + Null값 허용 여부를 설정해준다.

@Entity
public class Article {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; //내가 설정하는게 아니라 ID생성시 자동으로 값 부여

    //왜 Setter를 한꺼번에 안하고 일부러 나누냐면 id와 같이 민감한 정보는 변경되면 안되므로 별도로 지정하는것이다.
    @Setter @Column(nullable = false) private String title;
    @Setter @Column(nullable = false, length = 10000) private String content;
    @Setter private String hashtag;


    //JPA Auditing 자동 세팅하는 기능이 제공되어있음
    //com.board.boardproject하위에 config package생성 -> JpaConfig(Jpa설정 class파일 생성)
    @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) private String modifiedBy;
}

참고로 nullable의 기본값은 true이다.

@Column(nullable = false, length = 최대길이값)

 

 

이후  어떠한 게시글을 생성할때 생성자를 지정해주는데, 굳이 2개를 쓰는 이유는 맨위의 Article은 게시글 생성시 생성되는  요소들이고,

아래의 public static Article의 경우에는 사용자에게 반드시 넣어야하는 요소들을 알려주기 위해 별도로 표시한것이다.

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

//위의 Article을 생성할때 무조건 채워야하는 부분을 알려주는 생성자이다.
public static Article of(String title, String content, String hashtag) {
    return new Article(title, content,hashtag);
}


//이후 특정한 게시글이 동일한지 여부를 확인할때(최적화) 롬복의 EntitiyEquals를 써도 되지만
//롬백에서는 모든 Entity를 비교하기 때문에 최적화상 불필요한 비교를 실행한다.
//이를 방지하기 위해서 equals() and hashcode()를 실행하여 고유한 값인 Id를 제외한 나머지의 값들은 비교군에서제외하는 방식을 아래와 같이 설정해준다.
//생성 -> equals() and hashcode() -> id를 제외한 나머지 체크해제 -> 나머진 체크하면 자동으로 아래와 같이 생성해준다.
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Article)) return false;
    Article article = (Article) o;
    return id.equals(article.id);

 

위의 코드를 좀더 간결하게하고 article 생성시 id가 없다면(어떠한 게시글도 없었을 경우를 상정)에는 비교작업을 진행하지 말라는 코드를 추가한 것이다.

package com.board.boardproject.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 javax.persistence.*;
import java.time.LocalDateTime;
import java.util.Objects;

@Getter
@ToString
@Table(indexes = {
        @Index(columnList = "title"),
        @Index(columnList = "hashtag"),
        @Index(columnList = "createdAt"),
        @Index(columnList = "createdBy")
})  //검색 가능하게 Index 설정
@Entity
public class Article {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; //내가 설정하는게 아니라 ID생성시 자동으로 값 부여

    //왜 Setter를 한꺼번에 안하고 일부러 나누냐면 id와 같이 민감한 정보는 변경되면 안되므로 별도로 지정하는것이다.
    @Setter @Column(nullable = false) private String title;
    @Setter @Column(nullable = false, length = 10000) private String content;
    @Setter private String hashtag;


    //JPA Auditing 자동 세팅하는 기능이 제공되어있음
    //com.board.boardproject하위에 config package생성 -> JpaConfig(Jpa설정 class파일 생성)
    @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) private String modifiedBy;


    //Private생성자는 아래에서는 사용불가능하다 왜냐하면 Article은 Entity라 Private사용 불가 최소 Protected
    protected Article(){}

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

    //위의 Article을 생성할때 무조건 채워야하는 부분을 알려주는 생성자이다.
    public static Article of(String title, String content, String hashtag) {
        return new Article(title, content,hashtag);
    }


    //이후 특정한 게시글이 동일한지 여부를 확인할때(최적화) 롬복의 EntitiyEquals를 써도 되지만
    //롬백에서는 모든 Entity를 비교하기 때문에 최적화상 불필요한 비교를 실행한다.
    //이를 방지하기 위해서 equals() and hashcode()를 실행하여 고유한 값인 Id를 제외한 나머지의 값들은 비교군에서제외하는 방식을 아래와 같이 설정해준다.
    //생성 -> equals() and hashcode() -> id를 제외한 나머지 체크해제 -> 나머진 체크하면 자동으로 아래와 같이 생성해준다.
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Article article)) return false;
        //아래 return부분을 해석하자면 id가 없다면(null)애초에 비교 불가능하니 비교작업을 진행하지말라는거고
        //id가 있다면 id끼리 equals 비교해서 동일할 경우 중복 게시글이라고 판단하라는 얘기다.
        return id != null && id.equals(article.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}
728x90
반응형