A Library Management System supported with recommendation system for users
Key Functionalities:-
- Maintaining membership data
- Maintaining book availability status
- Maintaining borrower info
- Maintaining/updating metadata of the books borrowed
- Listing top 'n' recommended books of each genre , based on the mostly borrowed by the users of the library in a particular genre
So, this is a library management application that enables one to manage library as admin but also allows users to get recommendations as per genre of their choice. this project solely uses SpringBoot and leverages it various functionalities by integrating dependencies. Like mysql-connector, Spring Web, Spring Data JPA , JDBC API enables one to connect to database and JPA repository provides several predefined functions to fetch data.
Also makes use of Postman & MySQL.
Book Entity @Entity @Table(name = "Book") public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Getter
@Setter
@NotBlank(message = "Title is mandatory!")
private String title;
@Getter
@Setter
@NotBlank(message = "Author is mandatory!")
private String author;
@Getter
@Setter
@NotNull(message = "Genre Id is mandatory!")
private int genreId;
@Setter
@Getter
@Min(value=1,message="At least one copy required!")
private int totalCopies=1;
@Getter
@Setter
@Min(value=0,message="Available copies can't be negative!")
private int availableCopies=1;
@Getter
@Setter
@Min(value=0,message="Borrow Count can't be negative!")
private int borrowCount;
public Book() {
}
public Book(int id, String title, String author, int genreId) {
this.title = title;
this.author = author;
this.genreId = genreId;
}
public int getBookId() {
return id;
}
@Min(value = 0, message = "Available copies can't be negative!")
public int getAvailableCopies() {
return availableCopies;
}
public void setAvailableCopies(@Min(value = 0, message = "Available copies can't be negative!") int availableCopies) {
this.availableCopies = availableCopies;
}
} Book Register Entity @Entity @Table(name="Book_Register") public class BookRegister { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id;
@Getter
@Setter
@ManyToOne
@JoinColumn(name="book_id", foreignKey = @ForeignKey(name="bookId"))
@NotNull(message="Book Id required")
private Book book;
@Getter
@Setter
@ManyToOne
@JoinColumn(name="user_id", foreignKey = @ForeignKey(name="userId"))
@NotNull(message="User Id required")
private User user;
@Getter
@Setter
@NotNull(message ="Borrow Date is mandatory!")
private Date borrowDate;
@Setter
@Getter
private Date returnDate;
public int getRecordId() {
return id;
}
public BookRegister(int id, Book book, User user, Date borrowDate, Date returnDate) {
this.book = book;
this.user = user;
this.borrowDate = borrowDate;
if (returnDate != null) {
this.returnDate = returnDate;
} else {
// Calculate returnDate based on borrowDate + 2 months
Calendar calendar = Calendar.getInstance();
calendar.setTime(borrowDate);
calendar.add(Calendar.MONTH, 2);
this.returnDate = calendar.getTime();
}
}
public BookRegister() {
}
} Genre Entity @Entity @Table(name = "Genre") public class Genre {
@Getter
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Getter
@NotBlank(message ="Genre Name required!")
@Column(name = "genre_name")
private String genreName;
public Genre() {
}
public Genre(int genreId, String name) {
this.genreName = name;
}
public void setName(String name) {
this.genreName = name;
}
} User Entity @Entity @Table(name="User") public class User { @Getter @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id;
@Setter
@Getter
@NotBlank(message = "User name required!")
private String userName;
@Setter
@Getter
private String status="Active";
@Setter
@Getter
private Date renewalDate= new Date(2025,6,1);
public User(int userId,String userName, String status, Date renewalDate) {
this.userName = userName;
this.status = status;
if(renewalDate != null) {
this.renewalDate = renewalDate;
}
else{
Calendar current_date= Calendar.getInstance();
current_date.add(Calendar.YEAR,1);
this.renewalDate= current_date.getTime();
}
}
public User() {
this.userName = "DefaultUserName";
this.status = "Active";
}
} API calls used in the application are: • Add a book Allows admin to add book or multiple books to the database API url: {{host}}:{{port}}/library/books/add Output:
• Borrow a book Allows admin to add a borrow record to the database API url: {{host}}:{{port}}/library/books/borrow?bookId=171&userId=5 Incase the user is inactive it returns “Inactive User”. Output:
API url: {{host}}:{{port}}/library/books/borrow?bookId=171&userId=51 Output:
• Return a book Allows admin to enter a return record to the database API url: {{host}}:{{port}}/library/books/return?bookId=113&userId=15 Incase recurrent entries are made, error message “Cannot return more Copies than total available.” is displayed” Output:
• Add a genre Allows admin to add a genre to the genre database API url: {{host}}:{{port}}/library/genres/add Output:
• Get genre details Allows admin to view genre details API url: {{host}}:{{port}}/library/genres/2 Output:
• Add a user Allows admin to add a user to the database API url: {{host}}:{{port}}/library/users/add Output:
• Get user details Allows admin to fetch a users detail from the database API url: {{host}}:{{port}}/library/users/120 Output:
• Get top recommendations Allows users to get top recommendations as per borrowing of books by readers of the library Query SELECT b.title, b.author,COUNT(br.id) borrow_count,(total_copies-COUNT(br.id)) available_copies FROM book_register br JOIN book b ON br.book_id = http://b.id JOIN genre g ON b.genre_id = g.id WHERE g.genre_name = "Fictional" GROUP BY b.title, b.author ORDER BY COUNT(br.id) DESC; API url: {{host}}:{{port}}/library/books/topRecommendations?genreName=Comic&recCount=8 Output:
Query Output: [ { "title": "V for Vendetta", "author": "Alan Moore", "borrowCount": 2, "availableCount": 48 }, { "title": "Watchmen", "author": "Alan Moore", "borrowCount": 2, "availableCount": 43 }, { "title": "Maus", "author": "Art Spiegelman", "borrowCount": 2, "availableCount": 45 }, { "title": "Bone", "author": "Jeff Smith", "borrowCount": 2, "availableCount": 39 }, { "title": "Hellboy", "author": "Mike Mignola", "borrowCount": 2, "availableCount": 37 }, { "title": "Akira", "author": "Katsuhiro Otomo", "borrowCount": 2, "availableCount": 35 }, { "title": "Ghost in the Shell", "author": "Masamune Shirow", "borrowCount": 2, "availableCount": 41 }, { "title": "One Piece", "author": "Eiichiro Oda", "borrowCount": 2, "availableCount": 48 } ]
Execution Commands Navigate to the Project Directory: Go to the main project directory where pom.xml is located:
cd /path/to/Readholics-main/Readholics-main
Build the Project: Use Maven to build the project. This will compile the code, resolve dependencies, and package the application:
./mvnw clean install
For Windows: Use mvnw.cmd instead:
mvnw.cmd clean install
Run the Application: To start the Spring Boot application:
./mvnw spring-boot:run
On Windows:
mvnw.cmd spring-boot:run
Access the Application: By default, Spring Boot applications run on http://localhost:8080. You can open this URL in a browser to interact with the application.