System Management Books CRUD application using Spring Boot, Spring Data JPA, Lombok, MapStruct, and MySQL.

by Starling Diaz

2. Setting Up the Project

Step 1: Create a Spring Boot Project

Go to Spring Initializr and set up a new Spring Boot project with the following settings:

  • Project: Maven Project
  • Language: Java
  • Spring Boot: 3.3.0 or the latest version
  • Group: com.mentorly
  • Artifact: book-management
  • Dependencies:
    • Spring Web
    • Spring Data JPA
    • Lombok
    • MySQL Driver
    • MapStruct

Download the project and extract it to your development environment.

3. Adding Dependencies

In the pom.xml file, make sure you have the following dependencies:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.starlingdiaz</groupId>
    <artifactId>book-management</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>book-management</name>
    <description>book-management</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
        <org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Map Struct-->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>17</source>
                        <target>17</target>
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>1.18.20</version>
                            </path>
                            <path>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>${org.mapstruct.version}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

4. Configuring Database Connection

In src/main/resources/application.yml, add the following configuration to connect to your MySQL database:

spring:
  application:
    name: book-management
    datasource:
      url: jdbc:mysql://localhost:3306/book_management
      username: your_username
      password: your_password
      driver-class-name: com.mysql.cj.jdbc.Driver

      jpa:
        hibernate:
          ddl-auto: update
        show-sql: true
        database-platform: org.hibernate.dialect.MySQL8Dialect
server:
  port: 8080

Replace your_username and your_password with your actual MySQL credentials.

5. Creating the Entity Class

Create an entity class called Book in the com.mentorly.book_management.entity package.

Book.java

/**
 * @author Starling Diaz on 10/31/2024.
 * @Github https://github.com/NSTLRD
 * @Website https://mentorly.blog/
 * @Academy https://www.mentor-ly.com/
 * @version book-management 1.0
 * @since 10/31/2024.
 */

package com.starlingdiaz.bookmanagement.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "books")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;
    private String author;
    private String genre;
    private double price;
    private int publicationYear;
}

This Book class represents a table in the database with fields for storing information about books.

6. Creating the Repository Interface

Create a repository interface called BookRepository in the com.mentorly.book_management.repository package.

BookRepository.java

/**
 * @author Starling Diaz on 10/31/2024.
 * @Github https://github.com/NSTLRD
 * @Website https://mentorly.blog/
 * @Academy https://www.mentor-ly.com/
 * @version book-management 1.0
 * @since 10/31/2024.
 */

package com.starlingdiaz.bookmanagement.repository;

import com.starlingdiaz.bookmanagement.entity.Book;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BookRepository extends JpaRepository<Book, Long>{
}

This repository interface extends JpaRepository, providing CRUD operations for the Book entity.

7. Creating the DTO Class

Create a BookDTO class in the com.mentorly.book_management.dto package to transfer data between the client and server.

BookDTO.java

/**
 * @author Starling Diaz on 10/31/2024.
 * @Github https://github.com/NSTLRD
 * @Website https://mentorly.blog/
 * @Academy https://www.mentor-ly.com/
 * @version book-management 1.0
 * @since 10/31/2024.
 */

package com.starlingdiaz.bookmanagement.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class BookDTO {
    private Long id;
    private String title;
    private String author;
    private String genre;
    private double price;
    private int publicationYear;
}

8. Creating the Mapper Interface

Create a BookMapper interface in the com.mentorly.book_management.mapper package. This interface will use MapStruct to map between Book and BookDTO.

BookMapper.java

/**
 * @author Starling Diaz on 10/31/2024.
 * @Github https://github.com/NSTLRD
 * @Website https://mentorly.blog/
 * @Academy https://www.mentor-ly.com/
 * @version book-management 1.0
 * @since 10/31/2024.
 */

package com.starlingdiaz.bookmanagement.mapper;

import com.starlingdiaz.bookmanagement.dto.BookDTO;
import com.starlingdiaz.bookmanagement.entity.Book;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper(componentModel = "spring")
public interface BookMapper {
    BookMapper INSTANCE = Mappers.getMapper(BookMapper.class);

    BookDTO toDTO(Book book);
    Book toEntity(BookDTO bookDTO);
}

9. Creating the Service Layer

Create a service interface BookService and its implementation BookServiceImpl in the com.mentorly.book_management.service package.

BookService.java

/**
 * @author Starling Diaz on 10/31/2024.
 * @Github https://github.com/NSTLRD
 * @Website https://mentorly.blog/
 * @Academy https://www.mentor-ly.com/
 * @version book-management 1.0
 * @since 10/31/2024.
 */

package com.starlingdiaz.bookmanagement.service;

import com.starlingdiaz.bookmanagement.dto.BookDTO;

import java.util.List;

public interface BookService {
    BookDTO createBook(BookDTO bookDTO);
    BookDTO updateBook(Long id, BookDTO bookDTO);
    void deleteBook(Long id);
    BookDTO getBookById(Long id);
    List<BookDTO> getAllBooks();
}

BookServiceImpl.java

/**
 * @author Starling Diaz on 10/31/2024.
 * @Github https://github.com/NSTLRD
 * @Website https://mentorly.blog/
 * @Academy https://www.mentor-ly.com/
 * @version book-management 1.0
 * @since 10/31/2024.
 */

package com.starlingdiaz.bookmanagement.service.Impl;

import com.starlingdiaz.bookmanagement.dto.BookDTO;
import com.starlingdiaz.bookmanagement.entity.Book;
import com.starlingdiaz.bookmanagement.mapper.BookMapper;
import com.starlingdiaz.bookmanagement.repository.BookRepository;
import com.starlingdiaz.bookmanagement.service.BookService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class BookServiceImpl implements BookService {

    private final BookRepository bookRepository;
    private final BookMapper bookMapper;

    @Override
    public BookDTO createBook(BookDTO bookDTO) {
        Book book = bookMapper.toEntity(bookDTO);
        Book savedBook = bookRepository.save(book);
        return bookMapper.toDTO(savedBook);
    }

    @Override
    public BookDTO updateBook(Long id, BookDTO bookDTO) {
        Book existingBook = bookRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Book not found"));
        existingBook.setTitle(bookDTO.getTitle());
        existingBook.setAuthor(bookDTO.getAuthor());
        existingBook.setGenre(bookDTO.getGenre());
        existingBook.setPrice(bookDTO.getPrice());
        existingBook.setPublicationYear(bookDTO.getPublicationYear());
        return bookMapper.toDTO(bookRepository.save(existingBook));
    }

    @Override
    public void deleteBook(Long id) {
        bookRepository.deleteById(id);
    }

    @Override
    public BookDTO getBookById(Long id) {
        Book book = bookRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Book not found"));
        return bookMapper.toDTO(book);
    }

    @Override
    public List<BookDTO> getAllBooks() {
        return bookRepository.findAll()
                .stream()
                .map(bookMapper::toDTO)
                .collect(Collectors.toList());
    }
}

10. Creating the Controller Layer

Create a BookController class in the com.mentorly.book_management.controller package. This controller will expose endpoints for CRUD operations.

BookController.java

/**
 * @author Starling Diaz on 10/31/2024.
 * @Github https://github.com/NSTLRD
 * @Website https://mentorly.blog/
 * @Academy https://www.mentor-ly.com/
 * @version book-management 1.0
 * @since 10/31/2024.
 */

package com.starlingdiaz.bookmanagement.controller;

import com.starlingdiaz.bookmanagement.dto.BookDTO;
import com.starlingdiaz.bookmanagement.service.BookService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/v1/books")
@RequiredArgsConstructor
public class BookController {

    private final BookService bookService;

    @PostMapping
    public ResponseEntity<BookDTO> createBook(@RequestBody BookDTO bookDTO) {
        return ResponseEntity.ok(bookService.createBook(bookDTO));
    }

    @PutMapping("/{id}")
    public ResponseEntity<BookDTO> updateBook(@PathVariable Long id, @RequestBody BookDTO bookDTO) {
        return ResponseEntity.ok(bookService.updateBook(id, bookDTO));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteBook(@PathVariable Long id) {
        bookService.deleteBook(id);
        return ResponseEntity.noContent().build();
    }

    @GetMapping("/{id}")
    public ResponseEntity<BookDTO> getBookById(@PathVariable Long id) {
        return ResponseEntity.ok(bookService.getBookById(id));
    }

    @GetMapping
    public ResponseEntity<List<BookDTO>> getAllBooks() {
        return ResponseEntity.ok(bookService.getAllBooks());
    }
}

11. Testing the CRUD Operations

To test the API, you can use Postman or curl commands. Here’s an example of each CRUD operation:

  • Create a Book: POST /api/v1/books
  • Update a Book: PUT /api/v1/books/{id}
  • Delete a Book: DELETE /api/v1/books/{id}
  • Get Book by ID: GET /api/v1/books/{id}
  • Get All Books: GET /api/v1/books

Summary

This tutorial provided a step-by-step guide to building a simple book management system using Spring Boot, Spring Data JPA, MapStruct, Lombok, and MySQL. This application covers a basic CRUD API and demonstrates the power of Spring Boot for rapid application development. With this guide, you now have a working system that can be further expanded with additional features as needed!

For more projects, tutorials, and resources, check out the links below:

Contact and Social Links

Feel free to contribute to the repository, share your feedback, or reach out if you have any questions. Happy coding!

Related Posts

About Us

We are Mentorly, your space for learning and practicing with real industry projects that will allow you to develop problem-solving skills with the best practices. Offering mentorships and real-world challenges to push you and support you in your professional development.

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More