MySQL 로 은행 데이터베이스 만들기 (Feat.JPA)

김태연·2024년 11월 7일

TmT 프로젝트

목록 보기
5/9

0. 서론

내가 만들려는 가계부 앱은 뱅크샐러드 의 클론코딩이다. 뱅크샐러드 는 메인화면에서 내가 가진 모든 계좌를 불러오고, 잔액의 흐름을 관리해주는 역할을 한다. 그러나 실제 금융원에서 제공하는 데이터를 나는 사용하지 못한다.
즉, 데이터를 불러오기 위해 나는 은행 데이터베이스를 모방해서 만들어야 한다!

1. 엔티티 만들기

가장 먼저 할 일은 기획이다. 그러나 여태 삽질을 하면서 기획에 대한 가닥이 잡혔기 때문에, 바로 개발로 들어간다! 만들어야 하는 엔티티는 총 5개, 은행, 계좌, 거래내역, 카테고리(거래내역을 분류하기 위함), 사용자 로 나누었다.

package com.ssafy.TmT.domain.account.entity;

import java.math.BigDecimal;
import java.util.List;

import com.ssafy.TmT.domain.member.entity.Member;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;

@Entity
@Table(name = "account") // 테이블 이름 명시
@Getter
@Setter
public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "account_id") // 컬럼 이름 명시
    private Long accountId;

    @Column(name = "account_number", length = 20, nullable = false) // 컬럼 길이 및 null 허용 여부 지정
    private String accountNumber;

    @Column(name = "balance", nullable = false)
    private BigDecimal balance;

    @ManyToOne(fetch = FetchType.LAZY)	// 조회할때만 갱신
    @JoinColumn(name = "member_id") // 외래 키 이름 명시
    private Member member;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "bank_id")
    private Bank bank;
    
    @OneToMany(mappedBy = "account", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Transaction> transactions;
}
package com.ssafy.TmT.domain.account.entity;

import java.sql.Timestamp;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "bank")
public class Bank {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long bankId;

    @Column(name = "bank_code", length = 10, nullable = false, unique = true)
    private String bankCode;

    @Column(name = "bank_name", length = 100, nullable = false)
    private String bankName;

    @Column(name = "swift_code", length = 11)
    private String swiftCode;

    @Column(name = "branch_code", length = 10)
    private String branchCode;

    @Column(name = "address", length = 200)
    private String address;

    @Column(name = "contact_number", length = 20)
    private String contactNumber;

    @Column(name = "created_at", updatable = false)
    private Timestamp createdAt;

    @Column(name = "updated_at")
    private Timestamp updatedAt;
}
package com.ssafy.TmT.domain.account.entity;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
public class Category {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonProperty("category_id")
    private Long categoryId;

    @JsonProperty("name")
    private String name;

    @JsonProperty("type")
    private String type; // 수입 또는 지출 구분

    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Transaction> transactions;
}
package com.ssafy.TmT.domain.account.entity;

import java.math.BigDecimal;
import java.sql.Timestamp;
import com.fasterxml.jackson.annotation.JsonProperty;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
public class Transaction {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonProperty("transaction_id")
    private Long transactionId;

    @JsonProperty("transaction_type")
    private String transactionType;

    @JsonProperty("amount")
    private BigDecimal amount;

    @JsonProperty("transaction_date")
    private Timestamp transactionDate;

    @JsonProperty("description")
    private String description;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "account_id")
    private Account account;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "category_id")
    private Category category;
}
package com.ssafy.TmT.domain.member.entity;

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

import com.ssafy.TmT.domain.account.entity.Account;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;

@Entity
@Table(name = "member") // 테이블 이름 명시
@Getter
@Setter
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id") // 컬럼 이름 명시
    private Long memberId;

    @Column(name = "name", length = 50, nullable = false)
    private String name;

    @Column(name = "email", length = 100, nullable = false, unique = true)
    private String email;
    
    @Column(name = "created_at", nullable = true)
    private Timestamp createdAt;

    @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Account> accounts;
}

엔티티를 만들 때 신경쓴 것들은
1. 관계매핑 (1:N, N:N 등..)
2. nullable, unique
3. lazy Fetch
이렇게 3가지가 있다.
1. 관계 매핑은 외래키 설정에 있어 매우 중요하기 때문에, 차근차근 생각해서 작성했다.
2. nullable 과 unique는 굳이 없어도 작동에는 큰 문제가 없지만, 금융 어플이니까 안정성을 높이고 싶어서 최대한 깐깐하게 작성했다.
3. lazy Fetch 는 데이터를 주고받을 때 DB 업데이트를 최소화하기 위해 적용시켰다.

DBeaver 를 이용하면 ERD를 자동으로 그려주기 때문에, JPA 만 실행시키면 쉽게 그릴 수 있다.

application.yaml 설정하기

spring:
  application:
    name: TmT

  datasource:
    url: jdbc:mysql://localhost:3306/testDB?useSSL=false&serverTimezone=UTC
    username: 사용자이름
    password: 사용자비밀번호
    driver-class-name: com.mysql.cj.jdbc.Driver
    
  jpa:
    hibernate:
      ddl-auto: update  # 자동으로 테이블을 생성 및 업데이트
    show-sql: true      # 콘솔에 실행된 SQL 쿼리를 출력
    properties:
      hibernate:
        format_sql: true  # SQL 쿼리를 보기 좋게 출력

application yaml 파일작성하는건 아주 신중하게..! 해야한다.
특히 jpa 설정의 ddl-auto 같은 경우에는, create 로 값을 설정해두면 프로젝트 실행시마다 테이블을 전부 drop 하고 새롭게 create 하기 때문에 데이터 손실의 위험이 있다! 잘 알아보고 설정해보자

profile
취업준비중입니다..!

0개의 댓글