1. 계좌 목록 조회 기능
작업 순서
1️⃣ AccountRepository 및 account.xml 쿼리 수정
2️⃣ AccountService에서 계좌 목록 조회 기능 추가
3️⃣ AccountController에서 계좌 목록 페이지 처리
4️⃣ account/list.jsp에서 계좌 목록 출력
계좌 목록 조회를 위한 Repository 코드 수정
AccountRepository.java
package com.tenco.bank.repository.interfaces;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.tenco.bank.repository.model.Account;
@Mapper
public interface AccountRepository {
public List<Account> findAllByUserId(@Param("userId") Integer principalId);
}
account.xml 쿼리 수정
<select id="findAllByUserId" resultType="com.tenco.bank.repository.model.Account">
select * from account_tb where user_id = #{userId}
</select>
- 특정 userId를 가진 계좌 목록을 조회하는 쿼리.
- MyBatis에서 @Param("userId")를 사용하여 매핑.
AccountService에서 계좌 목록 조회 기능 추가
package com.tenco.bank.service;
import com.tenco.bank.repository.interfaces.AccountRepository;
import com.tenco.bank.repository.model.Account;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import com.tenco.bank.handler.exception.DataDeliveryException;
import com.tenco.bank.handler.exception.RedirectException;
import java.util.List;
@Service
public class AccountService {
private final AccountRepository accountRepository;
public AccountService(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
}
public List<Account> readAccountListByUserId(Integer principalId) {
try {
return accountRepository.findAllByUserId(principalId);
} catch (DataAccessException e) {
throw new DataDeliveryException("계좌 목록 조회 실패", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
- 사용자 userId를 받아 해당 사용자의 계좌 목록을 조회.
- 예외 처리 후 적절한 메시지를 반환.
AccountController에서 계좌 목록 페이지 처리
package com.tenco.bank.controller;
import com.tenco.bank.repository.model.Account;
import com.tenco.bank.repository.model.User;
import com.tenco.bank.service.AccountService;
import jakarta.servlet.http.HttpSession;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/account")
public class AccountController {
private final HttpSession session;
private final AccountService accountService;
public AccountController(HttpSession session, AccountService accountService) {
this.session = session;
this.accountService = accountService;
}
@GetMapping("/list")
public String listPage(Model model) {
User principal = (User) session.getAttribute("principal");
if (principal == null) {
return "redirect:/user/sign-in";
}
List<Account> accountList = accountService.readAccountListByUserId(principal.getId());
model.addAttribute("accountList", accountList);
return "account/list";
}
}
- 로그인한 사용자의 계좌 목록을 조회.
- 조회된 계좌 목록을 account/list.jsp로 전달.
account/list.jsp에서 계좌 목록 출력
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/view/layout/header.jsp"%>
<div class="col-sm-8">
<h2>계좌 목록 🏦</h2>
<c:choose>
<c:when test="${not empty accountList}">
<table class="table">
<thead>
<tr>
<th>계좌 번호</th>
<th>잔액</th>
</tr>
</thead>
<tbody>
<c:forEach var="account" items="${accountList}">
<tr>
<td>${account.number}</td>
<td>${account.balance}</td>
</tr>
</c:forEach>
</tbody>
</table>
</c:when>
<c:otherwise>
<h5>아직 생성된 계좌가 없습니다.</h5>
</c:otherwise>
</c:choose>
</div>
<%@ include file="/WEB-INF/view/layout/footer.jsp"%>
- 계좌 목록이 있을 경우 테이블로 출력.
- 계좌가 없을 경우 안내 메시지를 표시.
2. 출금 기능 구현
출금 기능 개요
1️⃣ 출금 요청 페이지 (/withdrawal)
2️⃣ 입력값 검증 (계좌번호, 비밀번호, 금액 등)
3️⃣ 계좌 존재 여부 확인
4️⃣ 본인 계좌 여부 확인
5️⃣ 비밀번호 확인
6️⃣ 잔액 확인 (출금 가능 여부)
7️⃣ 출금 처리 (update 쿼리 실행)
8️⃣ 거래 내역 저장 (insert 쿼리 실행)
출금 요청을 위한 DTO (WithdrawalDTO)
package com.tenco.bank.dto;
import lombok.Data;
@Data
public class WithdrawalDTO {
private Long amount;
private String wAccountNumber;
private String wAccountPassword;
}
- 출금 요청 시 계좌번호, 비밀번호, 출금 금액을 입력받음.
출금 요청 페이지 (account/withdrawal.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/view/layout/header.jsp"%>
<div class="col-sm-8">
<h2>출금하기 💸</h2>
<form action="/account/withdrawal" method="post">
<div class="form-group">
<label for="wAccountNumber">출금 계좌 번호:</label>
<input type="text" name="wAccountNumber" class="form-control" required>
</div>
<div class="form-group">
<label for="wAccountPassword">비밀번호:</label>
<input type="password" name="wAccountPassword" class="form-control" required>
</div>
<div class="form-group">
<label for="amount">출금 금액:</label>
<input type="number" name="amount" class="form-control" required>
</div>
<button type="submit" class="btn btn-danger">출금하기</button>
</form>
</div>
<%@ include file="/WEB-INF/view/layout/footer.jsp"%>
- 사용자가 출금할 계좌번호, 비밀번호, 출금 금액을 입력.
출금 요청 처리 (Controller)
@PostMapping("/withdrawal")
public String withdrawalProc(WithdrawalDTO dto) {
User principal = (User) session.getAttribute("principal");
if (principal == null) {
return "redirect:/user/sign-in";
}
accountService.updateAccountWithdraw(dto, principal.getId());
return "redirect:/account/list";
}
- 로그인한 사용자의 출금 요청을 처리.
- AccountService.updateAccountWithdraw() 호출.
출금 처리 로직 (Service)
@Transactional
public void updateAccountWithdraw(WithdrawalDTO dto, Integer principalId) {
Account account = accountRepository.findByNumber(dto.getWAccountNumber());
if (account == null) {
throw new DataDeliveryException("존재하지 않는 계좌입니다.", HttpStatus.BAD_REQUEST);
}
account.checkOwner(principalId);
account.checkPassword(dto.getWAccountPassword());
account.checkBalance(dto.getAmount());
account.withdraw(dto.getAmount());
accountRepository.updateById(account);
historyRepository.insert(new History(dto.getAmount(), account.getId(), null));
}
- 계좌 존재 여부, 비밀번호 확인, 출금 가능 금액 확인 후 출금 처리.
- 거래 내역 저장 (History 테이블에 저장).
계좌 목록 조회 기능을 구현.
출금 기능을 상세하게 다뤄 계좌 검증 및 출금 과정 정리.
트랜잭션을 활용하여 데이터 무결성 유지.
🚀 다음 작업:
- 입금 기능 구현하기
- 계좌 이체 기능 추가