Jindory
Jindory의 기록 라이프
Jindory
전체 방문자
오늘
어제
06-27 09:35
  • 분류 전체보기
    • 개발
      • AI
      • Java
      • Javascript
      • JPA
      • Python
      • Spring
      • Web
    • 데이터베이스
      • Database
      • Oracle
      • MySQL
    • 코딩테스트
      • 구름IDE
      • 백준
      • 코딩테스트 준비
      • 프로그래머스
    • 분석 및 설계
      • Design Pattern
      • UML
    • 트러블슈팅
      • Java
      • JPA
      • Spring
    • 개발 커리어
      • 면접
      • 멘토링
      • 포트폴리오
      • 프로젝트

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

최근 댓글

최근 글

티스토리

250x250
hELLO · Designed By 정상우.
Jindory

Jindory의 기록 라이프

[Spring] Spring 초기 데이터베이스 데이터 설정 방법
개발/Spring

[Spring] Spring 초기 데이터베이스 데이터 설정 방법

2022. 7. 3. 22:36
반응형

안녕하세요. 개발자 Jindory입니다.

오늘은 Spring 서버 Start시 초기 데이터를 셋팅하는 방법에 대해서 작성해보고자 합니다.

 

# 글 작성 이유

김영한님의 '실전 스프링 부트와 JPA 활용 2'편을 보다가 API 테스트 시 기초 데이터를 셋팅하는 방법을 보고 정리해보고자 합니다. 저 또한 API 테스트 시 기초 데이터가 필요한 경우가 있는데, 테스트 할 때마다 SQL로 데이터를 입력하거나, API로 데이터를 생성하는 수고로움을 덜 수 있는 방법이라서 한번 정리해 보고자 합니다.


# 초기 데이터 생성 Component를 위한 설정

application.properties

Spring Boot 2.4부터 생긴 설정으로 현재 활성화된 프로필을 정의하기 위해서 설정하는 정보입니다.

spring.profiles.active에 자신이 원하는 프로필을 설정하며 test, dev, local, prod, uat 등 자신이 원하는 프로필을 작성하면 됩니다.

spring.profiles.active = dev

나머지 설정에 대해서 자세한 설명은 여기를 참고하시면 될것 같습니다.

# Database Setting

# MySQL 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# DB Source URL
spring.datasource.url=jdbc:mysql://localhost:3306/sports?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true
# DB username
spring.datasource.username=
# DB password
spring.datasource.password=
# DB Connection Test
spring.datasource.connection-test-query=SELECT 1

# local DB setting
spring.profiles.active=local

# JPA Setting
# JPA 사용시 사용 DB를 mysql로 설정
spring.jpa.database = mysql
# JPA로 쿼리 생성시 MySQL로 생성되도록 설정
spring.jpa.database-platform = org.hibernate.dialect.MySQL5InnoDBDialect
# JPA DDL 고유기능 사용 유무
spring.jpa.generate-ddl = false
# true 설정시 JPA 쿼리문 확인 가능
spring.jpa.show-sql=true
# DDL(create, alter, drop) 정의시 DB의 고유 기능을 사용할 수 있다.
spring.jpa.hibernate.ddl-auto= create
# JPA의 구현체인 Hibernate가 동작하면서 발생한 SQL의 가독성을 높여준다.
spring.jpa.properties.hibernate.format_sql=true

# hibernate logging
logging.level.org.hibernate = info

# 데이터를 만들기 위한 Entity, Repository, Service, Controller 생성

계정을 생성하는 Entity, Repository, Service Controller를 만들어 보겠습니다.

Account Entity

Email, Password, DisplayName, age, privateYn 속성을 가진 Entity를 만듭니다.

package jpabook.jpashop.domain;

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

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Entity
@Table(name="ACCOUNT")
@NoArgsConstructor
public class Account {
	
	@Id
	private String email;
	
	@Column(name = "PASSWORD", nullable = false, length = 50)
	private String password;
	
	@Column(length = 20,columnDefinition =" varchar(255) default 'guest'")
	private String displayName;
	
	@Column(length = 3,columnDefinition ="integer default 15")	
	private int age;
	
	@Column(length = 1,columnDefinition ="char(1) default 'N'")
	private char privateYn;
	
	@PrePersist
	public void prePersist() {
		// displayName이 null이면 default값으로 매핑 되도록 설정
		if(this.displayName == null) {
			this.displayName = "member";
		}
		else {
			this.displayName = this.displayName;
		}
		
		// age이 0이면 default값으로 매핑 되도록 설정
		if(this.age == 0) {
			this.age = 999;
		}
		else {
			this.age = this.age;
		}
		
		// privateYn이 '\u0000'이면 default값으로 매핑 되도록 설정
		if(this.privateYn == '\u0000') {
			this.privateYn = 'F';
		}
		else {
			this.privateYn = this.privateYn;
		}
	}
	
	public Account(String email,String pw,String displayName,int age,char privateYn) {
		this.email = email;
		this.pw = pw;
		this.displayName = displayName;
		this.age = age;
		this.privateYn = privateYn;
	}
	
	public Account(String email,String pw,String displayName,int age) {
		this.email = email;
		this.pw = pw;
		this.displayName = displayName;
		this.age = age;
	}
	
	public Account(String email,String pw,String displayName) {
		this.email = email;
		this.pw = pw;
		this.displayName = displayName;
	}
	
	public Account(String email,String pw) {
		this.email = email;
		this.pw = pw;
	}
	
}

Account Repository

JpaRepository를 상속 받아서 AccountRepository를 생성한다.

package jpabook.jpashop.repository;

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

import jpabook.jpashop.domain.Account;

public interface AccountRepository extends JpaRepository<Account,String> {

}

Account Service

기본적인 CRUD 기능이 제공되도록 Service를 구현합니다.

package jpabook.jpashop.service;

import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jpabook.jpashop.domain.Account;
import jpabook.jpashop.repository.AccountRepository;
import lombok.RequiredArgsConstructor;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class AccountService {
	
	private final AccountRepository accountRepository;
	
	
	public Account searchAccount(String email){
		return accountRepository.findById(email).orElse(null);
	}
	
	public List<Account> searchAccountAll(){
		return accountRepository.findAll();
	}
	
	public Account createAccount(Account account) {
		return accountRepository.save(account);
	}
	
	public Account updateAccount(Account account,String email) {
		Account rtnEntity = accountRepository.findById(email).orElse(null);
		rtnEntity.updateEntity(account);
		return rtnEntity;
	}
	
	public String deleteAccount(String email) {
		accountRepository.deleteById(email);
		return email;
	} 
}

Account Controller

Service와 마찬가지로 CRUD 중심으로 구현하며, API 호출이 가능하도록 @RestController 어노테이션을 만듭니다.

package jpabook.jpashop.api;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import jpabook.jpashop.domain.Account;
import jpabook.jpashop.service.AccountService;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class AccountController {
	
	private final AccountService accountService;
	
	@GetMapping("searchAccount")
	public ResponseEntity<?> searchAccount(@RequestParam("email")String email){
		return new ResponseEntity<>(accountService.searchAccount(null),HttpStatus.OK);
	}
	
	@GetMapping("searchAccountAll")
	public ResponseEntity<?> searchAccountAll(){
		return new ResponseEntity<>(accountService.searchAccountAll(),HttpStatus.OK);
	}
	
	@PostMapping("createAccount")
	public ResponseEntity<?> createAccount(@RequestBody Account account){
		return new ResponseEntity<>(accountService.createAccount(null),HttpStatus.OK);
	}
	
	@PutMapping("updateAccount")
	public ResponseEntity<?> updateAccount(@RequestBody Account account,@RequestParam("email")String email){
		return new ResponseEntity<>(accountService.updateAccount(account, email),HttpStatus.OK);
	}
	
	@DeleteMapping("deleteAccount")
	public ResponseEntity<?> deleteAccount(@RequestParam String email){
		return new ResponseEntity<>(accountService.deleteAccount(email),HttpStatus.OK);
	}
}

# 초기 데이터를 생성하기 위한 Init Database 만들기

InitDb라는 class를 만들고 Spring에서 Component로 등록하고 local 서버가 실행될때만 초기 데이터를 생성해야하므로, @Profile정보를 설정합니다.(만일 이 정보를 설정하지 않으면, Test Code 실행시에도 초기데이터 생성이 실행되어 테스트 케이스가 다 실패할 수도 있다.)

또한 @PostContruct 어노테이션을 선언하여, 빈 생성시 특정 메서드가 실행될 수 있도록 등록합니다.

메서드에서 서버가 실행되었을때, 생성할 데이터를 만드는 소스코드를 작성하면 서버 시작시 초기 데이터가 셋팅이 됩니다.

package jpabook.jpashop;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import jpabook.jpashop.domain.Account;
import jpabook.jpashop.domain.Address;
import lombok.RequiredArgsConstructor;

@Component
@Profile("local")
@RequiredArgsConstructor
public class InitDb {
	
	private final InitService initService;
	
	@PostConstruct
	public void init() {
		initService.initDb();
	}
	
	@Component
	@Transactional
	@RequiredArgsConstructor
	static class InitService {
		
        private final EntityManager em;
		
		public void initDb() {
			Account account1 = new Account("user1@gmail.com","qwer1234","member1",25,'Y');
			Account account2 = new Account("user2@gmail.com","qwer1234","member2",38,'N');
			Account account3 = new Account("user3@gmail.com","qwer1234","member3",17,'N');
			Account account4 = new Account("user4@gmail.com","qwer1234","member4",49,'Y');
			Account account5 = new Account("user5@gmail.com","qwer1234","member5",52,'N');
			em.persist(account1);
			em.persist(account2);
			em.persist(account3);
			em.persist(account4);
			em.persist(account5);
		}
}

Post맨으로 데이터를 호출하면 아래와 같이 초기 데이터가 생성되어 있음을 확인 할 수 있습니다.


이렇게 Spring 서버 Start시 초기 데이터를 셋팅하는 방법에 대해서 알아봤습니다.

 

혹시라도 정정할 내용이나 추가적으로 필요하신 정보가 있다면 댓글 남겨주시면 감사하겠습니다.

오늘도 Jindory 블로그에 방문해주셔서 감사합니다.

 

[참고]

https://www.baeldung.com/spring-profiles

반응형
저작자표시 비영리 (새창열림)

'개발 > Spring' 카테고리의 다른 글

[Spring] Component Scan이란?  (2) 2024.05.27
[Spring] Transaction Propagation Model과 Isolation Level  (0) 2024.02.11
[Spring] 의존성 주입의 정의 및 의존성 주입 3가지 방식 (생성자 주입, 수정자 주입, 필드 주입)  (0) 2022.04.30
[Spring Boot] Thymeleaf 사용하기  (0) 2022.03.06
[Spring] @RequestParam과 @PathVariable의 차이는?  (0) 2022.02.20
    '개발/Spring' 카테고리의 다른 글
    • [Spring] Component Scan이란?
    • [Spring] Transaction Propagation Model과 Isolation Level
    • [Spring] 의존성 주입의 정의 및 의존성 주입 3가지 방식 (생성자 주입, 수정자 주입, 필드 주입)
    • [Spring Boot] Thymeleaf 사용하기
    Jindory
    Jindory

    티스토리툴바