nyximos.log

Spring Boot + MySQL + JPA + Thymeleaf 로 CRUD 구현하기 03 데이터베이스 설계, 테이블 생성 본문

Programming/Spring Boot

Spring Boot + MySQL + JPA + Thymeleaf 로 CRUD 구현하기 03 데이터베이스 설계, 테이블 생성

nyximos 2022. 8. 3. 16:40

Spring Boot + Gradle + MySQL + JPA + Thymeleaf  환경에서 간단한 CRUD 예제를 만들어보자

이번 포스팅에서는 DB설계, 요구사항 정리, 테이블 생성을 해보자.

 

 

주요 기능

회원가입

로그인

게시글 등록

게시글 수정

게시글 삭제

게시글 조회 (일반 회원 조회수와 운영자 회원 조회수 따로 구분)

게시글 추천 

 

 

요구사항 정리

데이터베이스 설계 전 요구사항을 정리해야한다.

주요 기능 별로 상세하게 정리해보자.

간단한 CRUD 게시판을 만들기 위해 요구사항을 최소한으로 구성하였고,

CRUD가 끝나면 아이디/비밀번호 찾기, 글 검색, 글 정렬, admin 페이지, 페이징, 댓글/대댓글 등을 각자 추가 해보도록 하자. 

 

로그인

입력 - 아이디, 비밀번호

 

아이디, 비밀번호 불일치시 에러 메세지 반환

아이디, 비밀번호 일치시 메인 페이지 이동

 

회원가입 버튼 클릭시 페이지 이동

 

회원가입

입력 - 아이디, 비밀번호, 이름, 비밀번호 확인

 

아이디 중복 검사

비밀 번호 중복 검사

 

게시글 등록

입력 - 제목, 내용

 

게시글 수정

입력 - 제목, 내용

 

수정시 글 상세로 이동

 

게시글 삭제

삭제 시 글 목록으로 이동

 

게시글 목록 조회

제목, 등록일,일반회원 조회수, 운영자 조회수, 추천수, 작성자

 

게시글 상세 조회 (일반 회원 조회수와 운영자 회원 조회수 따로 구분)

제목, 내용, 등록일, 수정일, 작성자, 추천수

 

게시글 추천

클릭시 1씩 증가

 

 

 

 

데이터베이스 설계

https://www.erdcloud.com/

 

회원가입, 로그인 후 ERD를 생성 해보자.

 

 

 

 

 

 

오른쪽 상단에 설정 아이콘을 눌러 아래와 같이 설정해준다.

똑같이 할 필요는 없다!

 

 

 

 

 

 

왼쪽 툴바에서 네번째 아이콘을 이용하여 엔티티를 생성할 수 있다.

 

 

 

노란색 + 아이콘은 PK 칼럼를 추가해고 파란색 + 아이콘은  기본 칼럼을 추가해준다.

 

 

 

왼쪽 툴바의 아이콘으로 연관관계를 표시할 수 있다.

 

 

 

 

 

 

 

난 이렇게 만들어 주었다.

각자 추가할 기능에 맞게 테이블, 칼럼을 수정하도록 하자.

 

이전 포스팅에서 정했던 컨벤션에 맞추어 이름을 정하도록 하자.

의미있는 이름을 짓는 것은 중요하다.

 

1. 소문자 사용

2. 가능하다면 약어를 피한다.

3. 복수의 단어로 이루어 질때는 underscore로 연결하는 snake case를 사용하자.

 

 

 

 

ERD CLOUD 말고도 아래 사이트를 사용할 수도 있다.

https://aquerytool.com/

 

AQueryTool

{{source.erd_info.erd_name + '(Ver ' + erdVersion + ', ' + source.erd_info.db_type + ')'}}

aquerytool.com

 

 

 

 

 

 

 

이제 인텔리제이로 돌아가 롬복이 적용되어 있는지 확인해보자.

 

롬복 적용

File - Settings

 

 

 

plugin 검색 후 설치

 

 

 

Annotation Processors - Enable annotation processing 체크 후 적용

 

출처: https://nyximos.tistory.com/55 [nyximos.log:티스토리]

 

 

 

 

도메인 작성

롬복을 적용했다면 도메인을 작성해보자.

 

MemberRole.java

public enum MemberRole {
    USER, ADMIN
}

 

Member.java

import lombok.*;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;

@Getter
@Entity
@Builder
@DynamicUpdate
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member {

    @Id
    @Column(name = "member_id", length = 20, nullable=false)
    private String id;

    @Column(name = "member_password", nullable = false)
    private String password;

    @Column(name = "member_name", nullable = false)
    private String name;

    @Enumerated(EnumType.STRING)
    @Column(name = "member_role", nullable = false)
    private MemberRole role;

}

 

Board.java

import lombok.*;
import org.hibernate.annotations.DynamicUpdate;

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

@Getter
@Entity
@Builder
@DynamicUpdate
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Board {

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "board_id", nullable = false)
    private Long id;

    @Column(name = "board_title", nullable = false)
    private String title;

    @Column(name = "board_content", columnDefinition = "TEXT", nullable = false)
    private String content;

    @Column(name = "board_created_at", nullable = false)
    private LocalDateTime createdAt;

    @Column(name = "board_updated_at", nullable = false)
    private LocalDateTime updatedAt;

    @Column(name = "board_admin_views", nullable = false)
    private int adminViews;

    @Column(name = "board_user_views", nullable = false)
    private int userViews;

    @Column(name = "board_likes", nullable = false)
    private int likes;

    @Enumerated(EnumType.STRING)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id", nullable = false)
    private Member member;

}

 

 

@Getter

Getter 메소드를 생성해준다.

 

🤓 Setter는 가급적 열지말자.

데이터가 변경되어 어느 지점에서 변경되는지 추적하기 힘들기 때문이다.

엔티티를 변경해야 할 일이 있다면  비즈니스 메서드를 만들어서 사용하도록 하자.

 

 

@Entity

JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 어노테이션을 필수로 붙여야 한다.

엔티티와 테이블 명을 다르게 하고 싶을 때는 @Table을 사용하자.

 

 

@Builder

빌더 패턴을 자동으로 생성해준다.

builder() : 빌더 클래스의 인스턴스 생성

build() : 실제 생성자 호출하여 객체 생성

 

빌더 패턴은 생성자에 인자가 많을 때 사용하면 편하다.

 

 

@DynamicUpdate

실제 값이 변경된 컬럼으로만 update 쿼리를 만들어주는 어노테이션

 

 

@AllArgsConstructor

@Builder와 @NoArgsConstructor를 함께 사용시 모든 매개 변수를 받는 생성자가 없으면 에러가 발생한다.

상세 설명은 여기 참고 [Lombok]  @Builder 사용 시 @NoArgsConstructor  관련 에러 해결

 

 

@NoArgsConstructor(access = AccessLevel.PROTECTED)

@Entity 적용시 기본생성자는 필수이기 때문에 롬복에서 제공하는 이 어노테이션을 사용한다.

 

@Id

기본키를 직접 할당할 필드에 적용한다.

 

@GeneratedValue(Strategy = GenerationType.AUTO)

개발자가 엔티티에 식별자를 직접 할당하지 않을시 식별자 생선 전략을 사용한다.

데이터베이스마다 개발하려는 의도마다 기본키 생성 방식이 달라지므로 확인해보고 사용하도록하자.

 

@Column

필드와 컬럼을 매핑할 때 사용한다.

 

@ManyToOne(fetch = FetchType.LAZY)

다대일 관계에서 사용한다.

fetch 속성은 글로벌 페치 전략을 설정할 때 사용하는데,

실무에서 모든 연관관계는 지연로딩 LAZY로 설정해야 한다.

@XToOne 관계는 default가 즉시 로딩(EAGER)이므로 직접 지연 로딩(LAZY)으로 설정해야 한다.

즉시 로딩은 예측이 어렵고, 어떤 SQL이 실행될 지 추적하기 어렵고 N+1문제가 자주 발생하기 때문이다.

 

@JoinColumn

외래키를 매핑할 때 사용한다.

 

@Enumerated(EnumType.STRING)

Enum 값을 String으로 저장하고 싶을 때 사용

이 어노테이션을 붙이지 않으면 정수가 저장된다. (0, 1, 2 ... )

 

 

 

이 밖에도 사용되는 어노테이션이 많다. 

아래 링크를 참고하도록 하자.

https://nyximos.tistory.com/78

 

[JPA] 엔티티 매핑

자바 ORM 표준 JPA 프로그래밍 김영한 🚵‍♀️ @Entity JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 어노테이션을 필수로 붙여야 한다. @Entity 적용 시 주의사항 1. 기본 생성자는 필수 (파라미터

nyximos.tistory.com

 

 

 

 

 

 

 

서버를 실행하면 JPA가 데이터베이스 스키마를 자동으로 생성해준다.

JPA는 매핑정보와 데이터베이스 방언을 사용해서 데이터베이스 스키마를 생성한다.

생성되었는지 확인해보자.

 

 

데이터베이스 목록 조회

SHOW DATABASES;

 

사용할 데이터베이스 선택

USE [DATABASE명];

USE crud_test;

 

테이블 구조 확인

DESC [TABLE명];

DESC member;
DESC board;

 

 

 

성공 ~

 

 

 

 

틀린 부분이나 이해하기 어려운 부분이 있다면 댓글로 알려주세요.