자바 스프링/부트 블로그 JPA 프로젝트

#11 insert 테스트와 enum 사용법

daramG 2022. 5. 6. 20:33

 

회원가입을 위한 insert 테스트

 

DummyControllerTest.java 작성

 

실행결과 :

 

스프링은 이렇게 더 강력한 기능을 제공한다.

실행결과 :

성공적으로 값이 잘 받아진다.

 

이제 회원가입을 위한 insert 테스트를 진행해보자

 

우선 UserRepository를 만들자.

com.cos.blog.repository 패키지를 만들고 그 곳에 Interface인 UserRepository.java 를 만든다.

 

extends JpaRepository를 한다.

 

JpaRepository에는 User테이블이 들고 있는 모든 행을 다 리턴하는 findAll() 함수가 있다.

 

또 PagingAndSortingRepository.class에는 정렬을 하거나 페이징을 해서 받는 등의 함수가 있다.

따라서 이런 함수들을 직접 작성하지 않아도 된다.

extends 했기 때문에 UserRepository가 이제 다 들고있기 때문이다.

 

UserRepository.java

package com.cos.blog.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.cos.blog.model.User;

// DAO
// 자동으로 bean 등록이 된다.
// @Repository 생략이 가능하다.
public interface UserRepository extends JpaRepository<User, Integer>{
// 해당 JpaRepository는 User테이블을 관리하는 Repository이다.
// 그리고 User테이블의 Primary key는 Integer이다.
}

 

 

DummyControllerTest.java

package com.cos.blog.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cos.blog.model.User;
import com.cos.blog.repository.UserRepository;

@RestController // 페이지를 리턴하는 것이 아니므로 RestController
public class DummyControllerTest {
	
	// @Autowired 전에는 null값이다.
	// ↓ 의존성 주입 // Autowired로 UserRepository를 메모리에 띄워준다.
	@Autowired // UserRepository 타입으로 스프링이 관리하고 있는 객체가 있다면 userRepository로 넣어라
	private UserRepository userRepository;
	
	//   http://localhost:9090/blog/dummy/join (요청)
	//   http의 body에 username, password, email 데이터를 가지고 (요청)
	@PostMapping("/dummy/join") // 회원가입(insert) 해야하니 PostMapping
	public String join(User user) {
		// @RequestParam("username") String u 이렇게해도 username이 변수 u에 딱 들어옴
		System.out.println("id : "+user.getId());
		System.out.println("username : "+user.getUsername());
		System.out.println("password : "+user.getPassword());
		System.out.println("email : "+user.getEmail());
		System.out.println("role : "+user.getRole());
		System.out.println("createDate : "+user.getCreateDate());
		
		userRepository.save(user);
		return "회원가입이 완료되었습니다.";
	}
}

 

실행결과 :

role빼고는 다 잘 들어온 것을 확인할 수 있다.

그럼 role은 왜 안들어왔을까?

 

우선, id는 @GeneratedValue(strategy = GenerationType.IDENTITY) 사용으로

auto_increment를 적용시켰었으니 당연히 자동으로 들어온다.

createDate도 @CreationTimestamp 사용으로 데이터가 insert나 update 될 때 시간이 자동으로 입력된다.

이 둘은 userRepository.save(user); 될 때 데이터가 들어가는 것이다.

 

그런데 role같은 경우는 현재 설정된 Default Value가 user이다.

이 Default Value가 작동하려면 (createDate, email, password, role, username) 값을 넣을 때 작동하는 것이 아니라

(createDate, email, password, username) 를 넣을 때 작동한다!!

(createDate, email, password, role, username)해서 null값을 넣어버리면 그대로 role에 null값이 들어가는 것이다.

 

그런데 대체 이 role 필드를 어떻게 제외할까?

이 방법은 간단하다.

@DynamicInsert 를 사용하는 것이다. 이는 insert할 때 null인 필드를 제외시켜준다.

 

따라서 User에 @DynamicInsert를 다음과 같이 import해서 적용시켜주고

 

실행해보면

이제 성공적으로 Default Value인 user가 적용된 것을 확인할 수 있다.

@DynamicInsert 사용을 통해 insert할 때 null인 필드가 제외되었기 때문이다.

 

그런데 어노테이션을 덕지덕지 붙이면 결코 좋은 것은 아니기 때문에

User.java에서 @DynamicInsert을 삭제하고, @ColumnDefault("'user'")도 삭제하자

 

현재 User.java

package com.cos.blog.model;
import java.sql.Timestamp;

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

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

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

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder // 빌더 패턴
@Entity // User 클래스가 MySQL에 테이블이 생성된다.
public class User {
	
	@Id // Primary key
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	// 프로젝트에서 연결된 DB의 넘버링 전략을 따라간다. 즉, MySQL일 경우 auto_increment를 사용한다는 것이다.
	private int id; // 시퀀스(오라클), auto_increment로 넘버링(MySQL)
	
	@Column(nullable = false, length = 30) // null이 될 수 없고, 30자 이상이 될 수 없다.
	private String username; // 아이디
	
	@Column(nullable = false, length = 100) // 비밀번호 암호화한 해쉬 넣어볼 예정이므로 길게 설정
	private String password;
	
	@Column(nullable = false, length = 50)
	private String email;

	private String role;
	// admin, user, manager ...
	// 정확히는 Enum을 사용하는 것이 좋다. Enum을 사용하면 어떤 데이터의 도메인(범위)을 만들 수 있다.
	// role이 String이므로 adminn과 같은 오타를 낼 수가 있다. Enum을 사용하면 이를 방지할 수 있다.
	
	@CreationTimestamp // 데이터가 insert나 update 될 때 시간이 자동으로 입력된다.
	private Timestamp createDate;
}

 

그리고 DummyControllerTest.java에

user.setRole("user"); 코드를 추가하였다.

 

enum 사용법

 

그런데 이렇게 코드를 추가할 때 개발자가 실수로 user가 아니라 userr 같은 오타를 낼 수도 있는데,

이를 방지하는 방법이 있다.

 

Enum Type 파일을 만들고

 

User.java

User.java 파일에서 private String role; 을 private RoleType role;로 바꿔준다.

그런데, DB는 RoleType이라는 것이 없기 때문에 해당 Enum이 String이라고 DB에 알려주어야한다.

따라서 다음과 같은 어노테이션을 작성한다.

 

그리고 DummyControllerTest.java 파일에 들어가보면

DummyControllerTest.java

이렇게 오류가 떠 있을 것이다.

당연히 User.java에서 role의 타입을 String이 아니라 RoleType으로 명시했기 때문에 String이 들어갈 수 없다.

따라서 다음과 같이 코드를 다시 작성한다.

 

DummyControllerTest.java

 

실행결과 :

 

깔끔하게 값이 전달되었다.

 

 

+ 추가

application.yml에 들어가서 

ddl-auto를 update로 해준다.

create로 되어있으면 저장할 때 마다 기존 데이터가 다 삭제된다.

 

 

학습자료 : https://youtu.be/oOJR2XCagdA