(3) 엔티티(Entity)

엔티티 구상 및 작성하기


시작하기 전에

개요 : 질문과 답변을 할 수 있는 게시판 서비스를 스프링부트를 통해 만들어 본다.

학습사이트 : https://wikidocs.net/book/7601

예제 코드 : https://github.com/pahkey/sbb


사용할 툴과 미리 익혀놓을 개념에 대해서 알아보자


H2 데이터베이스

주로 개발용이나 소규모 프로젝트에서 사용되는 파일 기반의 경량 데이터베이스. (참고 사이트 : https://kukim.tistory.com/105)

  • 세팅 순서
    • gradle파일 dependoncies에 아래 코드 추가

        runtimeOnly 'com.h2database:h2'
      
    • application.properties 파일에 아래 코드 추가

        # DATABASE
              
        # 콘솔 접속 허용여부
        spring.h2.console.enabled=true
              
        # 콘솔 접속을 위한 URL
        spring.h2.console.path=/h2-console
              
        # 데이터베이스 접속을 위한 경로 ->  디렉토리
        spring.datasource.url=jdbc:h2:~/local
              
        # 데이터베이스 접속시 사용하는 드라이버
        spring.datasource.driverClassName=org.h2.Driver
              
        # 사용자명 / 패스워드
        spring.datasource.username=sa
        spring.datasource.password=
      
    • 홈 디렉토리에 local.mv.db 파일 생성


  • 접속
    • URL : http://localhost:8080/h2-console 1
    • 연결 버튼을 클릭하면 local.mv.db파일과 연결됨


ORM (Object-Relational Mapping)

  • Class와 RDB의 테이블을 매핑한다는 뜻
  • 객체를 통해 간접적으로 데이터베이스 데이터를 다룬다


JPA (Java Persistence API)

  • Java에서 ORM 기술 표준으로 사용하는 인터페이스 모음
  • JPA를 구현한 대표적 실제 클래스에는 하이버네이트등이 있다
  • 자바 프로그램에서 DB에 데이터를 저장하거나 조회하려면 JPA사용


  • 세팅 순서
    • gradle파일 dependoncies에 아래 코드 추가

        implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
      
    • application.properties 파일에 아래 코드 추가

        # JPA
              
        # DB엔진 종류 설정
        spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
              
        # 엔티티를 기준으로 테이블을 생성하는 규칙을 정의. 아래의 코드는 update
        spring.jpa.hibernate.ddl-auto=update
        # 개발 환경에서는 보통 update 모드를 사용하고 운영환경에서는 
        # none(엔티티가 변경되더라도 데이터베이스를 변경하지 않음) 또는
        # validate(변경사항이 있는지 검사만 ) 모드를 사용한다.
      

엔티티(Entity)란

  • 데이터베이스 테이블과 매핑되는 자바 클래스
  • 우리가 만들려는 웹사이트는 질문과 답변을 할 수 있는 게시판 서비스이므로, 질문과 답변에 해당하는 엔티티가 있어야 한다.


엔티티 속성 구상

  • 질문 엔티티
속성명 설명
id 질문의 고유 번호
subject 질문의 제목
content 질문의 내용
create_data 질문을 작성한 일시


  • 답변 엔티티
속성명 설명
id 답변의 고유 번호
question 질문(어떤 질문의 답변인지 알아야 함)
content 답변의 내용
create_data 답변을 작성한 일시

엔티티 작성하기

질문 엔티티

  • Question.java
package com.mysite.sbb;

import java.time.LocalDateTime;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
public class Question {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	
	@Column(length = 200)
	private String subject;
	
	@Column(columnDefinition = "TEXT")
	private String content;
	
	private LocalDateTime createDate;
}
  • @Entity
    • 에너테이션을 적용해야 JPA가 엔티티로 인식.
  • @Id
    • id에너테이션을 적용하면 고유번호적용 → primary key
  • @GeneratedValue
    • strategy : 고유번호를 생성하는 옵션
    • IDENTITY : 해당 컬럼만의 독립적인 시퀀스 생성
    • 해당 속성에 값을 따로 세팅하지 않아도 1씩 자동증가
  • Colums
    • 테이블의 컬럼 세부 설정
    • (length = 200) : subject의 길이 200
    • (columnDefinition = “TEXT”) : 글자 수를 제한할 수 없는 경우 사용


참고사항

  • 테이블의 컬럼명
    • 위의 Question 엔티티에서 작성일시에 해당하는 createDate 속성의 실제 테이블의 컬럼명은 create_date가 된다.
    • 대소문자 형태의 카멜케이스(단어 중간에 대문자가 들어가는 표기) 는 언더바(_)로 치환되어 실제 테이블 컬럼명이 된다.
  • 엔티티와 Setter
    • 일반적으로 엔티티에는 Setter 메서드를 구현하지 않고 사용하기를 권한다. 왜냐하면 엔티티는 데이터베이스와 바로 연결되어 있으므로 데이터를 자유롭게 변경할 수 있는 Setter 메서드를 허용하는 것이 안전하지 않다고 판단하기 때문이다.
    • Setter 메서드 없이 값을 저장하는 방법 : 엔티티를 생성할 경우에는 롬복의 @Builder 어노테이션을 통한 빌드패턴을 사용하고, 데이터를 변경해야 할 경우에는 그에 해당되는 메서드를 엔티티에 추가하여 데이터를 변경하면 된다.
    • 단 “점프 투 스프링부트”에서는 원활한 설명을 위해 엔티티에 Setter 메서드를 사용.


답변 엔티티

  • Answer.java
package com.mysite.sbb;

import java.time.LocalDateTime;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
public class Answer {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	
	@Column(columnDefinition = "TEXT")
	private String content;
	
	private LocalDateTime createDate;
	
	@ManyToOne
	private Question question;
}
  • @ManyToOne
    • 이름 그대로 N : 1 관계 (하나의 질문엔 여러개의 답변이 달릴 수 있다)
    • Answer 엔티티가 Question엔티티를 참조해야한다
    • 참조키(외래키) 관계
    • 답변 엔티티의 question 속성은 어떤 질문의 답변인지 알아야 하기 때문에 추가된 속성이다. 따라서 ManyToOne 에너테이션을 추가해줘야 한다
  • @OneToMany
    • 반대방향 : Question 엔티티가 Answer 를 참조하는 방법
    • 하나의 질문에 답변은 여러개이므로 Question 엔티티 의 속성은 List 형태로 구현해야 함
    • Question.java파일에 아래의 코드 추가
      // import 추가
      import java.util.List;
      import javax.persistence.OneToMany;
        
      public class Question {
        	
      	// Question 클래스에 아래의 코드 추가
      	@OneToMany(mappedBy = "question", cascade = CascadeType.REMOVE)
      	private List<Answer> answerList;
      }
    
    • mappedBy
      • 참조 엔티티의 속성명을 의미한다.
    • cascade
      • 연쇄삭제
      • 질문이 삭제되면 달려있는 답변도 모두 삭제되어야 한다.

테이블 확인

  • 코드 저장 후 h2 데이터베이스 접속

2

  • ANSWER과 QUESTION 테이블 생성됨.
    • 생성되지 않을 시 로컬 서버 재시작
  • Question.java파일에 createDate를 creteDate라 오타를 내어 한 칼럼이 더 생성됨….
    • h2콘솔에서 아래의 sql문 실행
    • ALTER TABLE QUESTION DROP COLUMN CRETE_DATE
    • 컬럼을 삭제하는 sql문

Leave a comment