YeaLow
article thumbnail

User 클래스를 생성하고 실행하면 테이블이 자동으로 생긴다.

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity	//User클래스가 MySQL에 테이블이 생성이 된다.
//@DynamicInsert	//Insert 시에 Null인 필드를 제외시켜준다.
public class User {

	@Id	//Primary key
	@GeneratedValue(strategy = GenerationType.IDENTITY)	//프로젝트에서 연결된 DB의 넘버링 전략을 따라간다.
	private int id; //시퀀스,auto_increment
	
	@Column(nullable = false, length = 30)
	private String username; //아이디
	
	@Column(nullable = false, length = 100)	//비밀번호 암호화 예정이므로 글자수 넉넉하게줌.
	private String password;
	
	@Column(nullable = false, length = 50)
	private String email;
	
	//@ColumnDefault("user")
	//DB는 RoleType이라는게 없다.
	@Enumerated(EnumType.STRING)
	private RoleType role;	//Enum을 쓰는 게 좋다.	//ADMIN,USER
	
	@CreationTimestamp	//시간이 자동으로 입력됨.
	private Timestamp createDate;
}

 

이때 주의할 점은 application.yml 파일에 ddl-auto 항목이 create로 되어 있어야 자동으로 생성된다.

그런데 create를 설정해놓으면 실행할 때마다 기존에 user테이블이 있어도 삭제 후 새로 만들어지기 때문에 테이블을 한 번 생성하고 나면 update로 바꾸어주어야 한다.

 

실행하면 아래와 같이 콘솔창에 create문이 생기면서 MySQL에 테이블이 생긴다.

 

마찬가지로 Board 테이블, Reply 테이블도 생성해 준다.

import java.sql.Timestamp;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.CreationTimestamp;

@Entity
public class Board {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY) //auto_increment
	private int id;
	
	@Column(nullable = false, length = 100)
	private String title;
	
	@Lob //대용량 데이터
	private String content;	//섬머노트 라이브러리 <html>태그가 섞여서 디자인됨.
	
	@ColumnDefault("0")
	private int count;	//조회수
	
	@ManyToOne	(fetch = FetchType.EAGER)//Many = Board, User = One (한 명의 user는 여러 개의 게시글을 쓸 수 있다.)
	@JoinColumn(name = "userId")
	private User user;	//DB는 오브젝트를 저장할 수 없다. FK,자바는 오브젝트를 저장할 수 있다.
	
	//mappedBy : 연관관계의 주인이 아니다(난 FK가 아니예요.) DB에 컬럼을 만들지 마세요.
	@OneToMany(mappedBy = "board", fetch = FetchType.EAGER)	//하나의 게시글은 여러 개의 답변을 가질 수 있다.
	private List<Reply> reply;
	
	@CreationTimestamp
	private Timestamp createDate;
}
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Reply {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;
	
	@Column(nullable = false, length = 200)
	private String content;
	
	@ManyToOne //하나의 게시글에는 여러 개의 답변이 올 수 있다.
	@JoinColumn(name = "boardId")
	private Board board;
	
	@ManyToOne	//하나의 user는 여러 개의 답변을 달 수 있다.
	@JoinColumn(name = "userId")
	private User user;
	
	@CreationTimestamp
	private Timestamp createDate;
}

 

  • 기존에는 FK로 외래키를 지정해 주었는데 스프링부트에서는 @JoinColumn을 선언해주면 된다.
  • 그런데 연관관계를 생각해서 선언해 주어야 하는데 위의 코드를 보면 @ManyToOne이라는 것이 선언되어 있다. 댓글 테이블과 게시판 테이블을 엮어준다고 생각하면 하나의 게시글에는 여러 개의 답변이 올 수 있다. => 이 때에는 @ManyToOne을 선언해주면 된다.
  • 이렇게 어노테이션을 선언해 주면 아래와 같이 자동으로 board, user 테이블을 참조하는 것을 확인할 수 있다.


🤍INSERT (회원가입) 테스트

DummyController 클래스를 만들고 회원가입 코드를 작성한다.

 

Post매핑이기 때문에 Postman을 사용해서 회원가입 테스트를 진행해 본다.

아래와 같이 회원가입이 완료되었다.

 

조금 다른 방식으로도 insert가 가능하다.

포스트맨에 id는 설정하지 않았기 때문에 0으로 나온다.

 

  • DB에도 INSERT가 잘 되었지만 여기서 role 컬럼이 문제이다.

  • 테이블 생성 시 role 의 DefaultColumn값을 "USER"로 주었지만 이 개념은 아래와 같이 role을 제외하고 insert 시에만 적용된다.
INSERT
INTO
	User
    (createDate, email, password, username)
    values
    (?,?,?,?)

 

이때 Enum을 사용할 수 있다. EnumType 클래스를 생성해준다.

 

  • 아래와 같이 간단한 내용으로 enum을 생성하고 테이블의 타입을 RoleType으로 바꾼다.
  • DB에는 RoleType이라는게 없으므로 @Enumerated(EnumType.STRING)을 선언해준다.

 

여기까지 하고 데이터를 다시 INSERT하면 role컬럼의 값이 USER로 들어간 것을 확인할 수 있다.


🤍SELECT 테스트

1. 특정 회원 조회하기 : @PathVariable int id 사용

 

Get매핑이므로 브라우저에서 조회 가능하다.

없는 회원을 조회하면 아래와 같이 뜨도록 

 

코드를 수정해준다.

💡예외처리 클래스 작성

위와 같이 에러 페이지가 뜨지 않도록,

모든 예외처리를 받을 수 있도록 @ControllerAdvice 어노테이션을 사용하여 GlobalExceptionHandler 클래스를 생성해준다.

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

@ControllerAdvice	//모든 exception 이곳으로 들어오게 하는 어노테이션
@RestController
public class GlobalExceptionHandler {

		@ExceptionHandler(value = IllegalArgumentException.class)
		public String handleArgumentException(IllegalArgumentException e) {
			return "<h1>"+e.getMessage()+"</h1>";
		}
}

 

그러면 아래와 같은 페이지가 작동하는 것을 확인할 수 있다.

2. 전체 회원 조회하기 : findAll 사용

조회 결과

 

3. 조회+페이징 같이 하기

 

한 페이지에 2명의 유저만 조회되는 것을 확인할 수 있다.


🤍UPDATE 테스트

  • JSON 데이터로 받도록 @RequestBody 사용
  • json 데이터 요청 -> 스프링이 (MessageConverter의 Jackson 라이브러리 작동) Java Object로 변환해서 받아줌.
  • update 시에는 @PostMapping을 사용함.

1번 유저의 비밀번호와, 이메일을 아래와 같이 수정해준다.

수정이 잘 되었다.

 

  • 또다른 방식으로 save를 사용할 수 있는데 이렇게 되면 에러가 발생한다.
  • 우리는 password, email만 수정할 것인데 username이 null이기 때문이다.
  • 이때 setUsername으로 강제로 username을 넣어줄 수 있는데 이유는 save 함수는 id를 전달하여 데이터가 없으면 insert, 있으면 update를 해주기 때문이다.

 

  • 그렇기 때문에 우리는 save 함수를 사용하지 않고 더티체킹을 활용할 것이다.
  • @Transactional 어노테이션을 사용하면 save를 사용하지 않고도 값을 변경 시 데이터가 update된다.

트랜젝션을 걸고 다시 put 요청을 보내보면

 

save 함수를 사용하지 않고도 update가 잘된 것을 확인할 수 있다.

 


🤍DELETE 테스트

@DeleteMapping 사용

 

없는 아이디를 삭제할 경우 경고 메시지 출력

 

1번 유저를 삭제해 보면

 

삭제가 잘된 것을 확인할 수 있다.

 

profile

YeaLow

@YeaLow

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!