🚀 Limited-Time Offer! Get 90% OFF on My Udemy Courses Grab the Deal 🎯

Spring Boot REST API One-to-Many CRUD Operations Example

🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.

▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube

▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube

In this tutorial, we will demonstrate how to set up a one-to-many relationship between Author and Book entities using Spring Boot and Hibernate, and expose CRUD operations through a REST API.

Prerequisites

  1. Java Development Kit (JDK) 11 or higher: Ensure JDK is installed and configured on your system.
  2. Integrated Development Environment (IDE): IntelliJ IDEA, Eclipse, or any other IDE.
  3. Maven: Ensure Maven is installed and configured on your system.

Step 1: Create a Spring Boot Project

  1. Open your IDE and create a new Spring Boot project.
  2. Use Spring Initializr or manually create the pom.xml file to include Spring Boot and other required dependencies.
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>spring-boot-onetomany-example</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.0</version> <relativePath/> </parent> <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-web</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 

Explanation

  • spring-boot-starter-data-jpa: Includes Spring Data JPA with Hibernate.
  • spring-boot-starter-web: Includes Spring MVC for building web applications.
  • h2: An in-memory database for testing purposes.

Step 2: Configure the Application Properties

Configure the application.properties file to set up the H2 database.

spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.h2.console.enabled=true spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true 

Step 3: Create the Author Entity Class

Create a package named com.example.entity and a class named Author.

package com.example.entity; import jakarta.persistence.*; import java.util.HashSet; import java.util.Set; @Entity public class Author { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true) private Set<Book> books = new HashSet<>(); public Author() {} public Author(String name) { this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Book> getBooks() { return books; } public void setBooks(Set<Book> books) { this.books = books; } public void addBook(Book book) { books.add(book); book.setAuthor(this); } public void removeBook(Book book) { books.remove(book); book.setAuthor(null); } @Override public String toString() { return "Author{id=" + id + ", name='" + name + '\'' + '}'; } } 

Explanation

  • @Entity: Marks the class as an entity.
  • @Id: Marks the field as the primary key.
  • @GeneratedValue: Specifies the strategy for generating values for the primary key.
  • @OneToMany: Defines a one-to-many relationship with the Book entity.
  • mappedBy: Specifies the field in the Book entity that owns the relationship.
  • cascade: Specifies the cascade operations.
  • orphanRemoval: Specifies whether to remove orphaned entities.

Step 4: Create the Book Entity Class

Create a class named Book in the same package.

package com.example.entity; import jakarta.persistence.*; @Entity public class Book { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String title; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "author_id") private Author author; public Book() {} public Book(String title) { this.title = title; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Author getAuthor() { return author; } public void setAuthor(Author author) { this.author = author; } @Override public String toString() { return "Book{id=" + id + ", title='" + title + '\'' + '}'; } } 

Explanation

  • @Entity: Marks the class as an entity.
  • @Id: Marks the field as the primary key.
  • @GeneratedValue: Specifies the strategy for generating values for the primary key.
  • @ManyToOne: Defines a many-to-one relationship with the Author entity.
  • @JoinColumn: Specifies the foreign key column.

Step 5: Create Repository Interfaces

Create a package named com.example.repository and interfaces for Author and Book.

package com.example.repository; import com.example.entity.Author; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface AuthorRepository extends JpaRepository<Author, Long> {} 
package com.example.repository; import com.example.entity.Book; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface BookRepository extends JpaRepository<Book, Long> {} 

Step 6: Create Service Classes

Create a package named com.example.service and service classes for Author and Book.

package com.example.service; import com.example.entity.Author; import com.example.entity.Book; import com.example.repository.AuthorRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class AuthorService { @Autowired private AuthorRepository authorRepository; public Author save(Author author) { return authorRepository.save(author); } public List<Author> findAll() { return authorRepository.findAll(); } public Author findById(Long id) { return authorRepository.findById(id).orElse(null); } public void deleteById(Long id) { authorRepository.deleteById(id); } public Author addBook(Long authorId, Book book) { Author author = findById(authorId); if (author != null) { author.addBook(book); return save(author); } return null; } public Author removeBook(Long authorId, Long bookId) { Author author = findById(authorId); if (author != null) { Book book = author.getBooks().stream().filter(b -> b.getId().equals(bookId)).findFirst().orElse(null); if (book != null) { author.removeBook(book); return save(author); } } return null; } } 
package com.example.service; import com.example.entity.Book; import com.example.repository.BookRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class BookService { @Autowired private BookRepository bookRepository; public Book save(Book book) { return bookRepository.save(book); } public List<Book> findAll() { return bookRepository.findAll(); } public Book findById(Long id) { return bookRepository.findById(id).orElse(null); } public void deleteById(Long id) { bookRepository.deleteById(id); } } 

Step 7: Create Controller Classes

Create a package named com.example.controller and controller classes for Author and Book.

package com.example.controller; import com.example.entity.Author; import com.example.entity.Book; import com.example.service.AuthorService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/authors") public class AuthorController { @Autowired private AuthorService authorService; @PostMapping public Author createAuthor(@RequestBody Author author) { return authorService.save(author); } @GetMapping public List<Author> getAllAuthors() { return authorService.findAll(); } @GetMapping("/{id}") public Author getAuthorById(@PathVariable Long id) { return authorService.findById(id); } @DeleteMapping("/{id}") public void deleteAuthor(@PathVariable Long id) { authorService.deleteById(id); } @PostMapping("/{authorId}/books") public Author addBook(@PathVariable Long authorId, @RequestBody Book book) { return authorService.addBook(authorId, book); } @DeleteMapping("/{authorId}/books/{bookId}") public Author removeBook(@PathVariable Long authorId, @PathVariable Long bookId) { return authorService.removeBook(authorId, bookId); } } 
package com.example.controller; import com.example.entity.Book; import com.example.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/books") public class BookController { @Autowired private BookService bookService; @PostMapping public Book createBook(@RequestBody Book book) { return bookService.save(book); } @GetMapping public List<Book> getAllBooks() { return bookService.findAll(); } @GetMapping("/{id}") public Book getBookById(@PathVariable Long id) { return bookService.findById(id); } @DeleteMapping("/{id}") public void deleteBook(@PathVariable Long id) { bookService.deleteById(id); } } 

Step 8: Create Main Application Class

Create a package named com.example and a class named SpringBootOneToManyExampleApplication.

package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootOneToManyExampleApplication { public static void main(String[] args) { SpringApplication.run(SpringBootOneToManyExampleApplication.class, args); } } 

Step 9: Run the Application

  1. Run the SpringBootOneToManyExampleApplication class.
  2. Use an API client (e.g., Postman) or a web browser to test the endpoints.

Testing the Endpoints

  1. Create an Author:

    • URL: POST /authors
    • Body:
      { "name": "George Orwell" } 
  2. Create Books:

    • URL: POST /books
    • Body:
      { "title": "1984" } 
    • Body:
      { "title": "Animal Farm" } 
  3. Add Books to Author:

    • URL: POST /authors/{authorId}/books
    • Body:
      { "title": "1984" } 
    • Body:
      { "title": "Animal Farm" } 
  4. Get All Authors:

    • URL: GET /authors
  5. Get Author by ID:

    • URL: GET /authors/{id}
  6. Get All Books:

    • URL: GET /books
  7. Get Book by ID:

    • URL: GET /books/{id}
  8. Delete Author by ID:

    • URL: DELETE /authors/{id}
  9. Delete Book by ID:

    • URL: DELETE /books/{id}

Conclusion

You have successfully created an example using Spring Boot and Hibernate to demonstrate a one-to-many relationship in an e-commerce context. This tutorial covered setting up a Spring Boot project, configuring Hibernate, creating entity classes with a one-to-many relationship, and performing CRUD operations through RESTful endpoints.

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare