H2 DB는 간단히 활용할 수 있는 메모리/파일 관계형 DB이며 가볍고 빠르기 때문에 개발 단계에 활용하거나 테스트코드에서도 자주 활용되는 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 : 어플리케이션 기동 시점에 테이블 생성, 종료 시점에 테이블 삭제.(운영에서는 사용 절대 금지!)
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 상속 받기
계정 추가 완료

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();
}
}
출력 결과
