System Overview
The application provides two primary roles with distinct functionalities:
- Administrator: Manage books (Create, Read, Update, Delete) and manage user accounts.
- Member: Browse available books, borrow books, return books, and view personal borrowing history.
Project Architecture
The project follows a standard layered architecture to separate concerns:
- beans: POJOs representing domain entities (Book, Member, Transaction).
- dao: Data Access Object layer for database interactions.
- service: Business logic layer interfaces.
- service.impl: Concrete implementations of the service interfaces.
- controller: Handles user input and navigation flow.
- util: Utility classes, specifically for JDBC connection managemant.
- test: Entry point for running the application.
- lib: External dependencies (e.g., MySQL JDBC Driver).
Entity Definitions (Beans)
LibraryItem (Book)
package com.library.beans;
public class LibraryItem {
private int itemId;
private String title;
private String writer;
private int stock;
public LibraryItem() {}
public LibraryItem(int itemId, String title, String writer, int stock) {
this.itemId = itemId;
this.title = title;
this.writer = writer;
this.stock = stock;
}
// Getters and Setters
public int getItemId() { return itemId; }
public void setItemId(int itemId) { this.itemId = itemId; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getWriter() { return writer; }
public void setWriter(String writer) { this.writer = writer; }
public int getStock() { return stock; }
public void setStock(int stock) { this.stock = stock; }
@Override
public String toString() {
return "Item[ID=" + itemId + ", Title='" + title + '\'' + ", Author='" + writer + '\'' + ", Stock=" + stock + ']';
}
}
BorrowRecord (JieBook)
package com.library.beans;
import java.sql.Timestamp;
import java.util.Date;
public class BorrowRecord {
private int recordId;
private int memberId;
private int itemId;
private Date borrowDate;
private Date returnDate;
public BorrowRecord() {}
public int getRecordId() { return recordId; }
public void setRecordId(int recordId) { this.recordId = recordId; }
public int getMemberId() { return memberId; }
public void setMemberId(int memberId) { this.memberId = memberId; }
public int getItemId() { return itemId; }
public void setItemId(int itemId) { this.itemId = itemId; }
public Date getBorrowDate() { return borrowDate; }
public void setBorrowDate(Timestamp borrowDate) { this.borrowDate = borrowDate; }
public Date getReturnDate() { return returnDate; }
public void setReturnDate(Timestamp returnDate) { this.returnDate = returnDate; }
@Override
public String toString() {
return "Record[ID=" + recordId + ", Member=" + memberId + ", Item=" + itemId + ", Borrowed=" + borrowDate + ", Returned=" + returnDate + ']';
}
}
Member (User)
package com.library.beans;
public class Member {
private int userId;
private String username;
private String password;
private int type; // 1: Admin, 0: User
public Member() {}
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public int getType() { return type; }
public void setType(int type) { this.type = type; }
}
Controller Layer
AdminController
package com.library.controller;
import com.library.beans.BorrowRecord;
import com.library.beans.LibraryItem;
import com.library.beans.Member;
import com.library.service.LibraryService;
import com.library.service.impl.LibraryServiceImpl;
import java.util.List;
import java.util.Scanner;
public class AdminController {
private Scanner scanner = new Scanner(System.in);
private LibraryService service = new LibraryServiceImpl();
public void displayAdminMenu() {
System.out.println("ADMIN MENU: [1]List Books [2]Add [3]Edit [4]Delete [5]User Mgt [6]Logout");
int choice = scanner.nextInt();
switch (choice) {
case 1 -> listItems();
case 2 -> addNewItem();
case 3 -> modifyItem();
case 4 -> removeItem();
case 5 -> System.out.println("User management logic here...");
case 6 -> new AuthController().loginMenu();
}
}
private void listItems() {
List<LibraryItem> items = service.fetchAllItems();
items.forEach(System.out::println);
displayAdminMenu();
}
private void addNewItem() {
LibraryItem item = new LibraryItem();
System.out.print("Title: "); item.setTitle(scanner.next());
if (service.checkItemExists(item)) {
System.out.println("Conflict: Item exists.");
} else {
System.out.print("Author: "); item.setWriter(scanner.next());
System.out.print("Stock: "); item.setStock(scanner.nextInt());
if (service.saveItem(item) > 0) System.out.println("Added.");
}
displayAdminMenu();
}
private void modifyItem() {
System.out.print("Title to edit: ");
LibraryItem query = new LibraryItem();
query.setTitle(scanner.next());
if (service.checkItemExists(query)) {
LibraryItem updatedData = new LibraryItem();
System.out.print("New Title: "); updatedData.setTitle(scanner.next());
System.out.print("New Author: "); updatedData.setWriter(scanner.next());
System.out.print("New Stock: "); updatedData.setStock(scanner.nextInt());
service.updateItem(query, updatedData);
System.out.println("Update successful.");
} else {
System.out.println("Item not found.");
}
displayAdminMenu();
}
private void removeItem() {
System.out.print("ID to delete: ");
service.deleteItem(scanner.nextInt());
System.out.println("Deleted.");
displayAdminMenu();
}
}
MemberController
package com.library.controller;
import com.library.beans.BorrowRecord;
import com.library.beans.LibraryItem;
import com.library.beans.Member;
import com.library.service.LibraryService;
import com.library.service.impl.LibraryServiceImpl;
import java.util.List;
import java.util.Scanner;
public class MemberController {
private Scanner scanner = new Scanner(System.in);
private LibraryService service = new LibraryServiceImpl();
private Member currentMember;
public MemberController(Member member) {
this.currentMember = member;
}
public void displayMemberMenu() {
System.out.println("MEMBER MENU: [1]View Books [2]Borrow [3]Return [4]History [5]Logout");
int choice = scanner.nextInt();
switch (choice) {
case 1 -> browseBooks();
case 2 -> borrowItem();
case 3 -> returnItem();
case 4 -> viewHistory();
case 5 -> new AuthController().loginMenu();
}
}
private void browseBooks() {
service.fetchAllItems().forEach(System.out::println);
displayMemberMenu();
}
private void borrowItem() {
System.out.print("Enter Book ID to borrow: ");
int itemId = scanner.nextInt();
if (service.findItemById(itemId) == 1) {
if (service.hasActiveBorrow(currentMember, itemId) > 0) {
System.out.println("You already have this book borrowed.");
} else {
service.processBorrow(currentMember, itemId);
System.out.println("Borrow successful.");
}
} else {
System.out.println("Book not found.");
}
displayMemberMenu();
}
private void returnItem() {
System.out.print("Enter Book ID to return: ");
int itemId = scanner.nextInt();
int recordId = service.hasActiveBorrow(currentMember, itemId);
if (recordId > 0) {
service.processReturn(recordId, itemId);
System.out.println("Return successful.");
} else {
System.out.println("No active borrow record found for this book.");
}
displayMemberMenu();
}
private void viewHistory() {
List<BorrowRecord> records = service.getMemberRecords(currentMember);
records.forEach(System.out::println);
displayMemberMenu();
}
}
AuthController
package com.library.controller;
import com.library.beans.Member;
import com.library.service.AuthService;
import com.library.service.impl.AuthServiceImpl;
import java.util.Scanner;
public class AuthController {
Scanner scanner = new Scanner(System.in);
AuthService authService = new AuthServiceImpl();
public void loginMenu() {
System.out.println("WELCOME: [1]Login [2]Register");
int choice = scanner.nextInt();
if (choice == 1) performLogin();
else performRegistration();
}
private void performRegistration() {
Member m = new Member();
System.out.print("User: "); m.setUsername(scanner.next());
System.out.print("Pass: "); m.setPassword(scanner.next());
if (authService.isUsernameTaken(m)) {
System.out.println("Username taken.");
} else {
authService.register(m);
System.out.println("Registered! Please login.");
}
loginMenu();
}
private void performLogin() {
Member m = new Member();
System.out.print("User: "); m.setUsername(scanner.next());
System.out.print("Pass: "); m.setPassword(scanner.next());
Member loggedIn = authService.authenticate(m);
if (loggedIn != null) {
if (loggedIn.getType() == 1) new AdminController().displayAdminMenu();
else new MemberController(loggedIn).displayMemberMenu();
} else {
System.out.println("Invalid credentials.");
loginMenu();
}
}
}
Service Layer
LibraryService Interface
package com.library.service;
import com.library.beans.BorrowRecord;
import com.library.beans.LibraryItem;
import com.library.beans.Member;
import java.util.List;
public interface LibraryService {
List<LibraryItem> fetchAllItems();
int saveItem(LibraryItem item);
boolean checkItemExists(LibraryItem item);
void updateItem(LibraryItem oldItem, LibraryItem newItem);
void deleteItem(int id);
int findItemById(int id);
int hasActiveBorrow(Member m, int itemId);
void processBorrow(Member m, int itemId);
void processReturn(int recordId, int itemId);
List<BorrowRecord> getMemberRecords(Member m);
}
AuthService Interface
package com.library.service;
import com.library.beans.Member;
public interface AuthService {
boolean isUsernameTaken(Member m);
Member authenticate(Member m);
void register(Member m);
}
LibraryServiceImpl
package com.library.service.impl;
import com.library.beans.BorrowRecord;
import com.library.beans.LibraryItem;
import com.library.beans.Member;
import com.library.dao.LibraryDao;
import com.library.service.LibraryService;
import java.util.List;
public class LibraryServiceImpl implements LibraryService {
private LibraryDao dao = new LibraryDao();
@Override
public List<LibraryItem> fetchAllItems() { return dao.getAllItems(); }
@Override
public int saveItem(LibraryItem item) { return dao.insertItem(item); }
@Override
public boolean checkItemExists(LibraryItem item) { return dao.existsByTitle(item); }
@Override
public void updateItem(LibraryItem oldItem, LibraryItem newItem) { dao.update(oldItem, newItem); }
@Override
public void deleteItem(int id) { dao.remove(id); }
@Override
public int findItemById(int id) { return dao.checkId(id); }
@Override
public int hasActiveBorrow(Member m, int itemId) { return dao.findActiveBorrow(m, itemId); }
@Override
public void processBorrow(Member m, int itemId) {
dao.createBorrowRecord(m, itemId);
dao.decrementStock(itemId);
}
@Override
public void processReturn(int recordId, int itemId) {
dao.markAsReturned(recordId);
dao.incrementStock(itemId);
}
@Override
public List<BorrowRecord> getMemberRecords(Member m) { return dao.getHistory(m); }
}
Database Utility
package com.library.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBConnector {
private static final String DB_URL = "jdbc:mysql://localhost:3306/library_db";
private static final String DB_USER = "root";
private static final String DB_PASS = "root";
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
try {
return DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
} catch (SQLException e) {
throw new RuntimeException("Connection failed", e);
}
}
public static void closeAll(Connection c, PreparedStatement ps, ResultSet rs) {
try { if (rs != null) rs.close(); } catch (SQLException ignored) {}
try { if (ps != null) ps.close(); } catch (SQLException ignored) {}
try { if (c != null) c.close(); } catch (SQLException ignored) {}
}
}
Application Entry Point
package com.library.test;
import com.library.controller.AuthController;
public class Application {
public static void main(String[] args) {
System.out.println("--- Library Management System ---");
new AuthController().loginMenu();
}
}
Sample Run (Member Flow)
--- Library Management System ---
WELCOME: [1]Login [2]Register
2
User: member01
Pass: pass01
Registered! Please login.
WELCOME: [1]Login [2]Register
1
User: member01
Pass: pass01
MEMBER MENU: [1]View Books [2]Borrow [3]Return [4]History [5]Logout
1
Item[ID=1, Title='The Great Gatsby', Author='Fitzgerald', Stock=5]
Item[ID=2, Title='1984', Author='Orwell', Stock=3]
MEMBER MENU: [1]View Books [2]Borrow [3]Return [4]History [5]Logout
2
Enter Book ID to borrow: 1
Borrow successful.
MEMBER MENU: [1]View Books [2]Borrow [3]Return [4]History [5]Logout
1
Item[ID=1, Title='The Great Gatsby', Author='Fitzgerald', Stock=4]
Item[ID=2, Title='1984', Author='Orwell', Stock=3]
MEMBER MENU: [1]View Books [2]Borrow [3]Return [4]History [5]Logout
3
Enter Book ID to return: 1
Return successful.
MEMBER MENU: [1]View Books [2]Borrow [3]Return [4]History [5]Logout