H2 DB

박상윤·2023년 8월 10일

H2 DB는 간단히 활용할 수 있는 메모리/파일 관계형 DB이며 가볍고 빠르기 때문에 개발 단계에 활용하거나 테스트코드에서도 자주 활용되는 DB

H2 DB관련 설정(없어도 동작은 하지만 조금 더 편라하게 하기 위해)

spring:
	datasource:
    	url: jdbc:h2:mem:test
        username: sa
        password:
        driverClassName: org.h2.Driver
    h2:
    	console:
        	enabled: true
    jpa:
    	defer-datasource-initialization: true
        database-platform:H2
        hibernate:
        	ddl-auto : create-drop
        open-in-view: false
        properties:
        	hibernate:
            	format_sql: true
                show_sql:true

주요 옵션 설명

  • defer-datasource-initialization : 초기 데이터 입력을 진행할 수 있도록 하는 옵션(이 옵션이 없으면 테이블 생성 전에 초기 데이터 입력을 하려고 하게 됨), spring boot 2.5.0이상부터 필요한 옵션

  • hibernate.ddl-auto : create-drop : 어플리케이션 기동 시점에 테이블 생성, 종료 시점에 테이블 삭제.(운영에서는 사용 절대 금지!)

H2 DB 데이터 저장과 가져오기

Account Entity

package com.example.account.domain;

import jakarta.persistence.*;
import lombok.*;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder // Getter,
@Entity
public class Account { // Account table 설정

    // primary key
    @Id
    @GeneratedValue
    private Long id;

    private String accountNumber;

    @Enumerated(EnumType.STRING) // 0,1,2.. 숫자가 아닌 enum을 String 형태로 그대로 저장
    private AccountStatus accountStatus;
}

실행되는 쿼리문

create table account (id bigint not null, account_number varchar(255), account_status varchar(255) check (account_status in ('IN_USE','UNREGISTERED')), primary key (id))

계정 추가하기

Controller -> Service -> Repository

AccountController

package com.example.account.controller;

import com.example.account.service.AccountService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class AccountController { // service에만 의존
    private final AccountService accountService;

    @GetMapping("/create-account")
    public String createAccount(){
        accountService.createAccount(); // 계정 생성
        return "Success"; // 성공!
    }
}

AcccountService

package com.example.account.service;

import com.example.account.domain.Account;
import com.example.account.domain.AccountStatus;
import com.example.account.repository.AccountRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor // final, @NotNull
public class AccountService {
    private final AccountRepository accountRepository; // repository에만 의

    @Transactional
    public void createAccount() {
        //@Builder를 활용한 빌더 패턴
        Account account = Account.builder()
                .accountNumber("40000")
                .accountStatus(AccountStatus.IN_USE)
                .build();
        accountRepository.save(account);
    }
}

AccountRepository

package com.example.account.repository;

import com.example.account.domain.Account;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AccountRepository extends JpaRepository<Account, Long> {

}

JpaRepository 상속 받기

계정 추가 완료

만든 계정 DB에서 가져오기

Service

package com.example.account.service;

import com.example.account.domain.Account;
import com.example.account.domain.AccountStatus;
import com.example.account.repository.AccountRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor // final, @NotNull
public class AccountService {
    private final AccountRepository accountRepository; // repository에만 의

    @Transactional
    public void createAccount() {
        //@Builder를 활용한 빌더 패턴
        Account account = Account.builder()
                .accountNumber("40000")
                .accountStatus(AccountStatus.IN_USE)
                .build();
        accountRepository.save(account);
    }

    @Transactional
    public Account getAccount(Long id){
        // Optional에서 값을 꺼내는 방식은 별로 추천하지는 않는다.
        return accountRepository.findById(id).get();
    }
}

데이터 가져오기

Controller

package com.example.account.controller;

import com.example.account.domain.Account;
import com.example.account.service.AccountService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class AccountController { // service에만 의존
    private final AccountService accountService;

    @GetMapping("/create-account")
    public String createAccount(){
        accountService.createAccount(); // 계정 생성
        return "Success"; // 성공!
    }

    @GetMapping("/account/{id}")
    public Account getAccount(@PathVariable Long id){ // 이름이 같으면 생략 가능
        return accountService.getAccount(id);
    }
}

Service

package com.example.account.service;

import com.example.account.domain.Account;
import com.example.account.domain.AccountStatus;
import com.example.account.repository.AccountRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor // final, @NotNull
public class AccountService {
    private final AccountRepository accountRepository; // repository에만 의

    @Transactional
    public void createAccount() {
        //@Builder를 활용한 빌더 패턴
        Account account = Account.builder()
                .accountNumber("40000")
                .accountStatus(AccountStatus.IN_USE)
                .build();
        accountRepository.save(account);
    }

    @Transactional
    public Account getAccount(Long id){ // 계정 가져오기
        // Optional에서 값을 꺼내는 방식은 별로 추천하지는 않는다.
        return accountRepository.findById(id).get();
    }
}

출력 결과

0개의 댓글