본문 바로가기

프로젝트

[SpringBoot] JPA 테이블 생성

먼저 기존 erd에서 바뀐점이 하나 있는데, 각 신고 테이블에 유저 닉네임을 외래키로 제약조건을 걸어 놨다. (누가 신고했는지에 대해 반드시 값이 있어야 한다고 생각해서 걸어놓음.)
바뀐 erd

 


여튼 오늘은 JPA를 이용해 위의 테이블 관계대로 테이블을 생성할 생각이다. 그러기전에 먼저 JPA에 대해 간략하게 보자.

JPA

  • JPA는 ORM의 일종으로 객체를 기준으로 해서 DB의 테이블과 매핑 시켜주는 역할을 한다. 이게 말로만 하면 잘 이해가 안갈수도 있는데, 한마디로 기존에 Java와 DB를 연결 시키고 테이블을 생성할때

    "DB테이블을 SQL문 작성을 통해 생성 -> 자바에서 VO(or DTO) 클래스 만들기"

    이과정을 거쳤다. 하지만 JPA를 쓰게 되면 이과정이 정반대로 일어난다. 즉, 자바 객체를 중심으로 관계형 데이터 베이스 모델을 매핑해서 테이블을 조작하는 기술이다.

    이번에할 테이블 생성을 보면

    "model 패키지에서 Class작성(VO) -> 테이블 자동생성" 으로 이뤄진다.

1. Gradle에 의존성 추가.

dependencies부분에 jpa 의존성을 추가해준다.

dependencies {
	...
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'	
    ...
}

 

2. application.properties 설정

application.properties 혹은 yaml 파일에 JPA에 대한 설정을 해준다.

# JPA 설정
spring.jpa.open-in-view=true
# 스프링 실행시 @Entity가 있는 객체를 DB에 테이블 생성함. 테이블 전체 최초 생성 이후로는 create -> update로 바꿔주자.
spring.jpa.hibernate.ddl-auto=update
# 카멜표기법을 사용하기위함. 이거말고 다른전략은 내가 객체를 카멜로 표시해도 언더바로 바뀜.
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
# jpa 전략을 기본전략으로 안한다. 즉, DB의 넘버링 전략 따라가기 위함.
spring.jpa.hibernate.use-new-id-generator-mappings=false
# 콘솔창에 실행된 테이블을 보여줌
spring.jpa.show-sql=true
# 콘솔창에 보여지는 테이블을 정렬해서 보여줌
spring.jpa.properties.hibernate.format_sql=true

 

3. 패키지구성

아래 그림처럼 model 패키지를 만들고, VO(DTO)클래스들을 만들어준다.

 

4. 클래스 상세 내용

Member

package org.my.toyproject.model;

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

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

//ORM: 객체를 테이블로 매핑해주는 기술
//jpa에 대해 application에서 커스터마이징부터 해주자.
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity//Member클래스가 DB 테이블로 생성됨.
public class Member {
	
	@Id//PK
	//프로젝트에 연결된 DB의 넘버링 전략을 따라간다.
	//즉, 오라클의 경우 시퀀스를 따라감.
	//@GeneratedValue(strategy = GenerationType.IDENTITY)//시퀀스를 사용해야 할때 사용. 
	private String nick;
	
	@Column(nullable = false, length = 50)
	private String email;
	
	@Column(nullable = false, length = 100)//암호화 위해서 길이 넉넉하게.
	private String password;
	
	@Column(nullable = false, length = 30)
	private String name;
	
	@Column(nullable = false, length = 15)
	private int phone;
	
	@Column(nullable = false, length = 30)
	private String bankName;
	
	@Column(nullable = false, length = 200)
	private String bankAccount;
}

 

복합키

권한 테이블의 경우 복합키로 이뤄져 있다. 복합키를 Class로 만들기 위해서 먼저 Serializable를 상속받고 @Embeddable 를 이용해 복합키가 될 컬럼들을 정의해주고 -> Serializable를 상속받은 새로운 클래스에서 @EmbeddedId 를 이용해 복합키로 사용하면된다.

 

AuthorityKey -> 칼럼 정의

package org.my.toyproject.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class AuthorityKey implements Serializable{
	
	@Column(nullable = false, length = 100)
	private String authorityRole;
	
	@ManyToOne
	@JoinColumn(name="nick")
	private Member member;
	
}

 

 

Authority -> 실제 DB에 만들어지는 테이블

package org.my.toyproject.model;

import java.io.Serializable;

import javax.persistence.EmbeddedId;
import javax.persistence.Entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Authority implements Serializable{
	
	@EmbeddedId
	private AuthorityKey authorityKey;
	
}

 

이런식으로 모든 테이블에 대해 자바 클래스로 만들어주고, 서버를 키게되면 정의해놨던 spring.jpa.hibernate.ddl-auto=create 에 의해 자동적으로 테이블이 만들어지게 된다.

다만 주의할점은 테이블을 전부 만들었다면 반드시 update로 바꿔줘야한다. 안그럼 데이터 다날아감;

 

5. 어노테이션

테이블을 만들때 썼던 어노테이션에 대해 말하자면~

@Data - 이전에 GetterSetter 를 수동으로 만들었는데 이 어노테이션을 사용하면 자동으로 GetterSetter가 적용된다.


@NoArgsConstructor - 매개변수가 없는 생성자를 만들어준다.


@AllArgsConstructor - 모든인자가 포함된 생성자를 만들어준다.


@Builder - 이건..설명좀 힘든데, 만약 VO클래스를 사용할때 매개변수 4개짜리 생성자가 있고, 3개짜리는 없다면 기존에는 VO클래스에 3개짜리 생성자를 만들고 사용해야하지만.  빌더를 사용하게되면 걍바로 사용가능!


@Entity - 이 어노테이션을 명시해줘야 테이블이 생성된다. (테이블의 이름은 클래스 이름이되는데, 다른 이름으로 바꾸고 싶다면 @Table을 같이 사용하자!)

 

@Id - 기본키를 나타내는 어노테이션.

 

@Column - 테이블에 있는 칼럼들을 나타낸다

 

@ManyToOne - 예를들면 회원과 보드의 관계를 생각해보면 회원은 여러개의 게시물을 가질수 있다. 즉, 이둘의 연관관계에서 회원은 주인이 된다. -> Many:보드 / One:회원

 

@OneToMany - 나는 이걸쓰진 않았지만, 예를들어 게시물 상세보기에서 필요한 정보는 회원, 게시물, 댓글 테이블이 있을것이다. 이때 게시물 테이블과 회원 테이블은 조인을 해놨을것이기 때문에 해당 게시물에대한 회원 및 게시글 정보를 한번에 조회할 수 있을것이다.

하지만 댓글의 경우는 게시물테이블에서 조회가 불가능한데 이를 댓글까지 한번에 조회하려고 할때 쓸수 있다. 참고로 이렇게 쓸꺼면 반드시 @OneToMany(mapperId = "관계가 명시된 칼럼") 을 써줘야한다.

이말은,  "나는 연관관계 주인이 아니에요~ 정보는 갖고올껀데 DB에는 만들지 마세요~" 라는 의미가 된다.


@JoinColumn(name = "replyNo") - JPA 사용안하면 외래키가 있을때 키값 즉, 칼럼명을 VO에 명시해야하지만 이를 이용하게되면 객체 자체를 명시해줄 수 있다. 쉽게 이해하면 Member - Board 조인이라고 생각하면 편하다.

 

@Lob - 내용을 입력하는 경우 DB에서 보통 데이터 타입clob을 이용해 장문의 내용을 입력할수 있도록 도와준다. @Lob은 DB에 칼럼만들때 clob 타입으로 만들도록 해주는 어노테이션이다.

 

@GeneratedValue(strategy = GenerationType.SEQUENCE) - 이건 기본키가 어떤 전략을 따를건지 명시하는 어노테이션으로 오라클의 경우 시퀀스를 사용할때 쓴다. MySql이라면 GenerationType.IDENTITY를 이용하면 된다.

 

참고: lombok 라이브러리를 추가해야지 위의 @Data같은 어노테이션을 사용할수 있다. Gradle , Maven에 추가하도록하자!

 

 

현재까지 전체 VO클래스


★이슈사항

1. 처음에 테이블을 만들때 기본키를 시퀀스로 주려고했는데 에러가남.IDENTITY

->@GeneratedValue(strategy = GenerationType.IDENTITY) 에서 @GeneratedValue(strategy = GenerationType.SEQUENCE)  로 바꿔주고 해결.(오라클 사용)

 

2. 신고 테이블에 대한 생각.

->  신고 테이블에서 게시판 유형 테이블을 참조하는게 아니라 각 게시판테이블의 기본키를 외래키로 받고 제약조건을 걸고 싶은데 그러기엔 외래키 하나가 null값이 되야하는데 말이안됨... 좀더 고민이 필요.....

 

★다음에 할꺼

- 로그인, 회원가입 페이지 만들기!! (이쁘게는 신경쓰지말자)

- 회원가입 기능구현.(가능하다면 시큐리티 설정도 할수 있도록 하자)