It's going to be one day 🍀

안녕하세요! 매일 매일 공부하려고 노력하는 백엔드 개발자 지망생의 공부 흔적입니다.

Back-End/Java # 교육

[Java 교육] 사용자 정의 예외/트랜잭션

2jin2 2024. 2. 7. 16:55

[공부 내용 정리]

사용자 정의 예외 클래스의 목적

package chapter09;

public class DBService {
    public static void main(String[] args) {
        // 필수값 - Profile : (이름, 나이), 취미, 좋아하는 음식 ...
        try {
            save("name", "age", "hobby", "food");
        } catch (NotExistsNameException e) {
            // logging
        }
    }
    public static void save(String name, String age, String hobby, String food) throws NotExistsNameException{
        // DB save SQLException 예외 -> 필수값을 입력 못 받았을 때.
        if (name.equals("")) {
            throw new NotExistsNameException("이름이 비어있습니다. name: " + name);
        }

//        dbRepository.save(name, age, hobby, food); // 실제 로직은 여기 있음.
    }
}

→ 치명적인 오류를 막기 위해 방해하는 역할

 

bank 서비스로 예시를 들어보자~

package chapter09;

public class Account {
    private long balance;

    public Account() {
        balance = 0;
    }

    public long getBalance() {
        return balance;
    }

    public void deposit(long money) {
        balance = money;
    }
    public void withdraw(long money) throws BalanceInsufficientException {
        // 발생할 수 있는 논리적 오류 : 잔액이 부족할 경우
        if (balance < money) {
            throw new BalanceInsufficientException(
                    "잔액부족! 현재 잔액: " + balance+ ",출금하고자 하는 금액 :  "+money);
        }
        balance -= money;
    }
}

→ Account.java

package chapter09;

public class BalanceInsufficientException extends Exception {
    public BalanceInsufficientException(String message) {
        super(message);
    }
}

→ BalanceInsufficientException.java

package chapter09;

public class Bank {
    public static void main(String[] args) {
        Account account = new Account();
				
				// 예금
        account.deposit(2000);
        System.out.println(""+ account.getBalance());
				
				// 출금
        try {
            account.withdraw(3000);
        } catch (BalanceInsufficientException e) {
            System.out.println(e.getMessage());
        }

    }
}

→ Bank.java

  • 출금(withdraw) 메소드에서 잔고(balance) 필드와 출금액을 비교해서 잔고가 부족하면 BalanceInsufficientException 을 발생시키도록 함.
  • Account에서 throw new BalanceInsufficientException(); 으로 사용자 정의 예외를 발생시켰고, 해당 예외를 throws BalanceInsufficientException 으로 던져주었음 (호출처로 에러를 전달함)
  • 이렇게 던져주면 해당 메소드를 사용하는 Bank에서 try-catch문을 이용해 예외처리를 해야함.

throw와 throws의 차이

  • throw : 메소드 내에서 예외를 발생시키는데 사용됨
    • (throw new BalanceInsufficientException())
  • throws : 메소드 선언부에서 사용되며, 해당 메소드가 처리하지 않은 예외를 호출자에게 전달, 던짐
    • (public void withdraw(int money) throws BalanceInsufficientException)

예외 트랜잭션 처리 방법

 

트랜잭션 : 하나의 작업 단위

ex) 은행에서의 ‘송금’ 트랜잭션

  • 송금 ‘처리중’ 상태로 변경
  • 송금인 계좌에 돈이 빠져나감
  • 수금인 계좌에 돈이 채워짐
  • 송금 ‘완료’ 상태로 변경

롤백 : 작업 단위를 모두 취소하는 행위

트랜잭션 중간에 문제가 생기고 롤백을 하지 않으면 데이터의 정합성 위협받음.

 

데이터 정합성 : 데이터들의 값이 서로 일관성 있게 일치하는 것

ex) 은행에서의 ‘송금’ 트랜잭션 코드

package chapter09.transaction;

public class Account {
    private long balance;

    public Account(long money) {
        balance = money;
    }

    public long getBalance() {
        return balance;
    }

    public void deposit(long money) {
        balance = money;
    }
    public void withdraw(long money) throws BalanceInsufficientException {
        // 발생할 수 있는 논리적 오류 : 잔액이 부족할 경우
        if (balance < money) {
            throw new BalanceInsufficientException(
                    "잔액부족! 현재 잔액: " + balance+ ",출금하고자 하는 금액 :  "+money);
        }
        balance -= money;
    }
}

→ Account.java

package chapter09.transaction;

public class BalanceInsufficientException extends Exception {
    public BalanceInsufficientException(String message) {
        super(message);
    }
}

→ BalanceInsufficientException.java

package chapter09;

public class XXXException extends Exception{
    public XXXException(String message) {
        super(message);

    }
}

→ XXXException.java

package chapter09.transaction;

import chapter09.XXXException;

public class Bank {
    public static void main(String[] args) {
        Account sender = new Account(3000); // 송금인 계좌
        Account receiver = new Account(3000);
        // 수금인 계좌
        long beforeBalance = sender.getBalance();

        try {
            sender.withdraw(2000);
            throw new XXXException("에러 수동 발생");
        } catch (XXXException e) {
            // 에러 발생! 모두 취소
            sender.deposit(beforeBalance);
        } catch (BalanceInsufficientException e) {
            System.out.println("출금하려는 잔액 부족. 프로그램 종료");
        }
    }
}

→ Bank.java

 

이렇게 코드를 작성하면 송금 상태변경, 송금인 계좌출금, 수금인 계좌입금 작업 중 하나라도 실패할 경우 예외가 발생하여 계좌 간 송금 작업이 모두 취소됨!


Daily Quiz

https://github.com/drinkgalaxy/coding-practice/commits/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/0