Skip to main content

Create a Real-World Banking System with Spring Boot 3, JPA, MySQL & Postman

Are you looking to build a real-world project using Spring Boot and MySQL? In this tutorial, we'll walk you through creating a complete Banking Service REST API that supports full CRUD operations, money transfers, deposits, and withdrawals. Whether you're preparing for interviews or enhancing your portfolio, this hands-on project will give you practical experience with Spring Boot 3, Spring Data JPA, and RESTful API design.

In this post, you'll learn how to build a Banking Service REST API using:

  • ✅ Spring Boot 3.x

  • ✅ Java 17

  • ✅ MySQL

  • ✅ Postman for API testing

  • ✅ IntelliJ IDEA

GitHub Repo: https://github.com/TheDipDeveloper/Banking-Service-Application-REST-Api

By the end, you'll have a complete backend application that supports:

  • Creating bank accounts

  • Fetching account data

  • Deposits and withdrawals

  • Transferring funds between accounts

  • Deleting accounts


🛠️ Tech Stack

  • Java 17

  • Spring Boot 3.x

  • Spring Data JPA

  • MySQL

  • Lombok

  • Postman

  • IntelliJ IDEA


📁 Project Structure

project structure


com.dipdeveloper.bank │ ├── controller # API endpoints ├── service # Business logic ├── repository # JPA interfaces ├── entity # JPA Entity classes ├── request # Input DTOs ├── response # Output DTOs ├── mapper # Maps Entity ↔ DTO └── resources ├── static # Images for documentation └── application.properties # DB & server configs

📥 Getting Started

1. Generate the project from Spring Initializr

  • Project: Maven

  • Language: Java

  • Spring Boot: 3.x

  • Dependencies:

    • Spring Web

    • Spring Data JPA

    • MySQL Driver

    • Lombok

2. Open the project in IntelliJ IDEA


⚙️ Configure application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/bank_db spring.datasource.username=root spring.datasource.password=your_password spring.jpa.hibernate.ddl-auto=update
💡 Make sure to create bank_db in MySQL before running the app.

🧱 Core Components

✅ Entity

package com.dipdeveloper.bank.entity;

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

@Entity
@Table(name = "account")
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer accountNo;
private String accountHolderName;
private Long balance;
}

✅ Repository

package com.dipdeveloper.bank.repository;

import com.dipdeveloper.bank.entity.Account;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

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

✅ Service

Handles business logic like deposit, withdrawal, transfer.

package com.dipdeveloper.bank.service;

import com.dipdeveloper.bank.entity.Account;
import com.dipdeveloper.bank.mapper.AccountMapper;
import com.dipdeveloper.bank.repository.AccountRepository;
import com.dipdeveloper.bank.request.AccountRequest;
import com.dipdeveloper.bank.request.AmountRequest;
import com.dipdeveloper.bank.request.TransferRequest;
import com.dipdeveloper.bank.response.AccountResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class AccountService {
@Autowired
private AccountRepository accountRepository;

public AccountResponse save(AccountRequest accountRequest) {
Account newAccount = accountRepository
.save(AccountMapper.accountRequestToAccount(accountRequest));

return AccountMapper.accountToAccountResponse(newAccount);
}

public AccountResponse findById(Integer accountNo) {
Optional<Account> optionalAccount = accountRepository.findById(accountNo);

if(optionalAccount.isPresent()){
return AccountMapper.accountToAccountResponse(optionalAccount.get());
}

throw new RuntimeException("Account Not Found.");
}

public List<AccountResponse> findAll() {
return accountRepository.findAll().stream()
.map(account -> AccountMapper.accountToAccountResponse(account))
.collect(Collectors.toList());
}

public AccountResponse withdraw(AmountRequest amountRequest) {
Optional<Account> optionalAccount = accountRepository.findById(amountRequest.getAccountNo());

if(!optionalAccount.isPresent()){
throw new RuntimeException("Account Not Found.");
}

Account account = optionalAccount.get();

if(account.getBalance() < amountRequest.getAmount()){
throw new RuntimeException("Insufficient Balance");
}

account.setBalance(account.getBalance()-amountRequest.getAmount());
Account updatedAccount = accountRepository.save(account);

return AccountMapper.accountToAccountResponse(updatedAccount);
}

public AccountResponse deposit(AmountRequest amountRequest) {
Optional<Account> optionalAccount = accountRepository.findById(amountRequest.getAccountNo());

if(!optionalAccount.isPresent()){
throw new RuntimeException("Account Not Found.");
}

Account account = optionalAccount.get();

account.setBalance(account.getBalance()+amountRequest.getAmount());
Account updatedAccount = accountRepository.save(account);

return AccountMapper.accountToAccountResponse(updatedAccount);
}

public List<AccountResponse> transfer(TransferRequest transferRequest) {
Optional<Account> optionalFromAccount = accountRepository.findById(transferRequest.getFromAccountNo());
Optional<Account> optionalToAccount = accountRepository.findById(transferRequest.getToAccountNo());

if(!optionalFromAccount.isPresent() || !optionalToAccount.isPresent()){
throw new RuntimeException("Account Not Found.");
}

Account fromAccount = optionalFromAccount.get();
Account toAccount = optionalToAccount.get();

if(fromAccount.getBalance() < transferRequest.getAmount()){
throw new RuntimeException("Insufficient Balance");
}

fromAccount.setBalance(fromAccount.getBalance()-transferRequest.getAmount());
toAccount.setBalance(toAccount.getBalance()+transferRequest.getAmount());

Account updatedFromAccount = accountRepository.save(fromAccount);
Account updatedToAccount = accountRepository.save(toAccount);

return new ArrayList<>(Arrays.asList(
AccountMapper.accountToAccountResponse(updatedFromAccount),
AccountMapper.accountToAccountResponse(updatedToAccount)
));
}

public void delete(Integer accountNo) {
accountRepository.deleteById(accountNo);
}
}

✅ Controller

Exposes endpoints for API operations.

package com.dipdeveloper.bank.controller;

import com.dipdeveloper.bank.request.AccountRequest;
import com.dipdeveloper.bank.request.AmountRequest;
import com.dipdeveloper.bank.request.TransferRequest;
import com.dipdeveloper.bank.response.AccountResponse;
import com.dipdeveloper.bank.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/account")
public class AccountController {

@Autowired
private AccountService accountService;

// POST api to create a new account
@PostMapping("/add")
public ResponseEntity<AccountResponse> add(@RequestBody AccountRequest accountRequest){
AccountResponse accountResponse = accountService.save(accountRequest);
return new ResponseEntity<>(accountResponse, HttpStatus.CREATED);
}

// GET api to get the account detail
@GetMapping("/get/{accountNo}")
public ResponseEntity<AccountResponse> get(@PathVariable("accountNo") Integer accountNo){
AccountResponse accountResponse = accountService.findById(accountNo);
return new ResponseEntity<>(accountResponse, HttpStatus.OK);
}

// GET api to get all account detail
@GetMapping("/get/all")
public ResponseEntity<List<AccountResponse>> getAll(){
List<AccountResponse> accountResponseList = accountService.findAll();
return new ResponseEntity<>(accountResponseList, HttpStatus.OK);
}

// Put Api to withdraw amount
@PutMapping("/withdraw")
public ResponseEntity<AccountResponse> withdraw(@RequestBody AmountRequest amountRequest){
AccountResponse accountResponse = accountService.withdraw(amountRequest);
return new ResponseEntity<>(accountResponse, HttpStatus.OK);
}

// Put Api to deposit amount
@PutMapping("/deposit")
public ResponseEntity<AccountResponse> deposit(@RequestBody AmountRequest amountRequest){
AccountResponse accountResponse = accountService.deposit(amountRequest);
return new ResponseEntity<>(accountResponse, HttpStatus.OK);
}

// Put Api to transfer amount
@PutMapping("/transfer")
public ResponseEntity<List<AccountResponse>> transfer(@RequestBody TransferRequest transferRequest){
List<AccountResponse> accountResponseList = accountService.transfer(transferRequest);
return new ResponseEntity<>(accountResponseList, HttpStatus.OK);
}

// DELETE api to delete the account detail
@DeleteMapping("/delete/{accountNo}")
public ResponseEntity<?> delete(@PathVariable("accountNo") Integer accountNo){
accountService.delete(accountNo);
return new ResponseEntity<>("Account deleted successfully.", HttpStatus.OK);
}
}

🔌 API Endpoints

MethodURIDescription
POST/account/addCreate account
GET/account/get/{accountNo}Get account by ID
GET/account/get/allGet all accounts
PUT/account/depositDeposit money
PUT/account/withdrawWithdraw money
PUT/account/transferTransfer between
DELETE/account/delete/{accountNo}Delete account

📮 Test With Postman

1. Create Account

POST http://localhost:8080/account/add
{ "accountHolderName": "mondal", "balance": 5000 }


2. Get Account by ID

GET http://localhost:8080/account/get/1


3. Get All Accounts

GET http://localhost:8080/account/get/all


4. Withdraw

PUT http://localhost:8080/account/withdraw
{ "accountNo": 1, "amount": 200 }


5. Deposit

PUT http://localhost:8080/account/deposit
{ "accountNo": 1, "amount": 200 }


6. Transfer

PUT http://localhost:8080/account/transfer
{ "fromAccountNo": 1, "toAccountNo": 2, "amount": 100 }


7. Delete Account

DELETE http://localhost:8080/account/delete/1


📌 Conclusion

This project gives you hands-on experience with:

  • Layered architecture

  • REST API design

  • DTO usage

  • Spring Boot best practices

  • MySQL connectivity

  • Real-world banking scenarios


Comments

Popular posts from this blog

25+ Spring Data JPA Interview Questions with Answers, Explanations & Use Cases

  📘 Spring Data JPA Interview Questions (with Answers, Explanations & Use Cases) 1. What is JPA and how is it related to Spring Data JPA? Answer: JPA (Java Persistence API) is a Java specification for managing relational data. Spring Data JPA is a part of Spring Data that simplifies JPA usage by reducing boilerplate code. Use Case: Persisting Java objects (like User ) to a relational database without writing SQL. 2. What are the key annotations used in JPA? Answer: @Entity , @Table , @Id , @GeneratedValue , @Column , @ManyToOne , @OneToMany , etc. Explanation: These annotations map Java objects to database tables and relationships. Use Case: Creating a User entity with an auto-generated ID and fields mapped to table columns. 3. What is the difference between JPA and Hibernate? Answer: JPA is a specification; Hibernate is an implementation of that specification. Use Case: Using Hibernate as the default JPA provider in Spring Boot. 4. How do you define a p...

How to Send Emails in Spring Boot Using SMTP (With and Without Attachments)

Sending emails is a common requirement in modern web applications — for things like user registration, password resets, or notifications. In this tutorial, we’ll walk through how to send emails in a Spring Boot application using SMTP , specifically with Gmail’s SMTP server , and demonstrate how to send both plain emails and emails with attachments . 📺 Video Demo If you prefer watching over reading, here’s a full demo of this tutorial in action: 📁 GitHub Repo  Want the complete working code? Clone the GitHub link provided below which contains all the source code. Source Code GitHub Link: https://github.com/TheDipDeveloper/Spring-Boot-Sending-Email 🧰 Prerequisites Java 17 or above Maven Spring Boot 3.x A Gmail account  🚀 Step 1: Add Spring Boot Mail Dependency First, add all the required dependency on pom.xml file < dependencies > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring...