Spring Boot RESTful APIs for CRUD Operations

Introduction

Spring Boot is a popular framework that helps developers build and deploy applications quickly and easily. With Spring Boot, developers can create RESTful APIs that are reliable, scalable, and easy to maintain. In this blog post, we will walk through the process of building a RESTful API with Spring Boot. We will start by creating a new Spring Boot project using Spring Initializr, then we will import it into IntelliJ IDEA and build our API step by step.

Spring Boot RESTful APIs for CRUD Operations

Creating a new Spring Boot project using Spring Initializr

Spring Initializr is a web-based tool that generates the initial structure of a Spring Boot project. It allows you to choose the dependencies you need and configure your project quickly and easily. To create a new Spring Boot project using Spring Initializr, follow these steps:

  1. Open a web browser and go to the Spring Initializr website at https://start.spring.io/.
  2. Select Gradle as the build tool.
  3. Select the latest version of Spring Boot as the project version.
  4. Choose a group name and an artifact name for your project. These values will be used to generate the package name for your project.
  5. Add the following dependencies to your project:
    • Spring Web
    • Spring Data JPA
    • H2 Database
  6. Click the Generate button to generate the project.

Once you have generated the project, you will get a ZIP file that contains the project files. Extract the files to a directory on your computer.

Importing the project into IntelliJ IDEA

Now that we have created our Spring Boot project, we can import it into IntelliJ IDEA. IntelliJ IDEA is a popular IDE for Java development that provides a rich set of features to help you write and debug your code. To import the project into IntelliJ IDEA, follow these steps:

  1. Open IntelliJ IDEA.
  2. Click on File > New > Project from Existing Sources.
  3. Select the directory where you extracted the project files and click Open.
  4. In the Import Project dialog, select Gradle as the project format and click Next.
  5. In the Gradle settings dialog, make sure that the Use auto-import option is checked and click OK.
  6. IntelliJ IDEA will now import the project and set up the necessary dependencies.

Once the project has been imported, you can start building your RESTful API.

Building a RESTful API for CRUD Operations

Now that we have our project set up in IntelliJ IDEA, we can start building our RESTful API. We will start with a simple API that allows us to retrieve a list of books. To build this API, we will need to create a few classes and configure our application.

Creating a Book class

The first thing we need to do is create a Book class that represents a book in our system. To create the Book class, follow these steps:

  1. In IntelliJ IDEA, right-click on the src/main/java directory and select New > Java Class.
  2. In the New Java Class dialog, enter Book as the class name and click OK.
  3. Replace the contents of the Book class with the following code:
package com.example.demo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Book {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    private String title;
    private String author;
    private String description;
    private BigDecimal price;

    protected Book() {}

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    public Long getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public String getDescription() {
        return description;
    }
 
    public void setDescription(String description) {
        this.description = description;
    }
 
    public BigDecimal getPrice() {
        return price;
    }
 
    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}

The Book class represents a book in our system and is annotated with the @Entity annotation, which tells Spring Data JPA to create a database table for this class. The class has three properties: id, title, and author. The id property is annotated with @Id and @GeneratedValue to indicate that it is the primary key of the table and that its value should be generated automatically by the database. The constructor takes a title and an author as arguments, and the class has getter methods for all three properties.

Creating a BookRepository interface

The next thing we need to do is create a BookRepository interface that will provide us with the ability to interact with the database. To create the BookRepository interface, follow these steps:

  1. In IntelliJ IDEA, right-click on the src/main/java directory and select New > Java Interface.
  2. In the New Java Interface dialog, enter BookRepository as the interface name and click OK.
  3. Replace the contents of the BookRepository interface with the following code:
package com.example.demo;

import org.springframework.data.repository.CrudRepository;

public interface BookRepository extends CrudRepository<Book, Long> {

}

The BookRepository interface extends the CrudRepository interface, which provides us with basic CRUD (Create, Read, Update, Delete) operations for our Book class. We don’t need to write any implementation code for this interface, as Spring Data JPA will generate the necessary code for us at runtime based on the method signatures we define.

Creating a BookController class

The next thing we need to do is create a BookController class that will handle HTTP requests and responses for our API. To create the BookController class, follow these steps:

  1. In IntelliJ IDEA, right-click on the src/main/java directory and select New > Java Class.
  2. In the New Java Class dialog, enter BookController as the class name and click OK.
  3. Replace the contents of the BookController class with the following code:
package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BookController {

    @Autowired
    private BookRepository bookRepository;

    @GetMapping("/books")
    public Iterable<Book> getBooks() {
        return bookRepository.findAll();
    }
}

The BookController class is annotated with @RestController, which tells Spring MVC that this class will handle HTTP requests and responses. The class has a single method, getBooks(), which is annotated with @GetMapping to indicate that it will handle GET requests to the /books endpoint. The method returns an Iterable<Book>, which will be converted to a JSON array and returned to the client.

The method uses the bookRepository object, which is automatically injected by Spring via the @Autowired annotation, to retrieve all books from the database. The findAll() method is provided by the CrudRepository interface and returns an Iterable<Book> containing all books in the database.

Configuring the application

Finally, we need to configure our application to use the H2 database and expose our API over HTTP. To configure our application, follow these steps:

  1. Open the application.properties file in the src/main/resources directory.
  2. Replace the contents of the file with the following code:
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.h2.console.path=/h2-console
spring.jpa.hibernate.ddl-auto=create-drop

The application.properties file contains configuration properties for our Spring Boot application. The properties we have defined here configure our application to use an H2 in-memory database, which is useful for development and testing purposes. The file

also enables the H2 console, which provides a web-based interface for exploring the database.

Testing the API

Now that we’ve written our API code, we can test it by running the application and making requests to the /books endpoint. To test the API, follow these steps:

  1. In IntelliJ IDEA, click the Run button in the toolbar or press Shift+F10 to run the application.
  2. Open a web browser and navigate to http://localhost:8080/h2-console. This will open the H2 console, where we can verify that our database has been created and populated with data.
  3. In the JDBC URL field, enter jdbc:h2:mem:testdb as the database URL and click Connect.
  4. In the SQL statement field, enter SELECT * FROM BOOK and click Run.
  5. Verify that the console displays a list of books, including the two books we added earlier.
  6. Open a new browser tab and navigate to http://localhost:8080/books. This will make a GET request to our API and return a JSON array of all books in the database.

Spring Boot REST API Using MySQL, MariaDB Or Oracle

Spring Boot is a popular Java framework for building RESTful web services, and it provides out-of-the-box support for connecting to relational databases such as MySQL, MariaDB, and Oracle. In this guide, we’ll walk through the process of setting up a Spring Boot REST API with support for CRUD (Create, Read, Update, Delete) operations using either MySQL or MariaDB as the underlying database. We’ll cover everything from configuring the database connection to implementing the API endpoints for managing books in the database.

Spring Boot REST API Using MySQL

Let us add MySQL support for our CRUD operations. To do this, we’ll need to make a few changes to our code.

First, we’ll need to add the MySQL connector dependency to our build.gradle file. Add the following line to the dependencies section:

implementation 'mysql:mysql-connector-java:8.0.26'

Next, we’ll need to configure our database connection in our application.properties file. Add the following lines to the file:

spring.datasource.url=jdbc:mysql://localhost:3306/bookstore
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update

This configures our application to use the MySQL database named “bookstore”, with a username of “root” and password of “password”. The spring.jpa.hibernate.ddl-auto=update line tells Spring to automatically create or update our database schema based on our entity classes.

Next, we’ll need to update our Book entity class to work with our MySQL database. We’ll add some JPA annotations to our class to map it to the database table. Update the class to look like this:

@Entity
@Table(name = "books")
public class Book {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
 
    @Column(nullable = false)
    private String title;
 
    @Column(nullable = false)
    private String author;
 
    @Column(nullable = false)
    private String description;
 
    @Column(nullable = false)
    private BigDecimal price;
 
    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 String getAuthor() {
        return author;
    }
 
    public void setAuthor(String author) {
        this.author = author;
    }
 
    public String getDescription() {
        return description;
    }
 
    public void setDescription(String description) {
        this.description = description;
    }
 
    public BigDecimal getPrice() {
        return price;
    }
 
    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}

The @Entity annotation tells Spring that this class is a JPA entity, and the @Table(name = "books") annotation tells Spring to map this entity to a database table named “books”. We also added some annotations to each field to specify their column names and constraints.

Next, we’ll need to update our BookRepository interface to extend the JpaRepository interface provided by Spring Data JPA. This interface provides us with a set of convenient methods for performing common database operations. Update the interface to look like this:

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

Now we can use the methods provided by JpaRepository, such as save(), findById(), findAll(), deleteById(), and many more, to perform CRUD operations on our Book entity.

Finally, we’ll need to update our BookController to use our BookRepository to interact with the database. Update the constructor to inject an instance of BookRepository:

@RestController
@RequestMapping("/api/books")
public class BookController {
 
    private final BookRepository bookRepository;
 
    @Autowired
    public BookController(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }
 
    // ...
}

Now we can use the methods provided by BookRepository to handle incoming requests. For example, to create a new book in the database, we can use the save() method to persist a new Book object:

@PostMapping
public Book createBook(@RequestBody Book book) {
    return bookRepository.save(book);
}

Similarly, to retrieve all books from the database, we can use the findAll() method:

@GetMapping
public List<Book> getAllBooks() {
    return bookRepository.findAll();
}

To retrieve a single book by ID, we can use the findById() method:

@GetMapping("/{id}")
public ResponseEntity<Book> getBookById(@PathVariable(value = "id") Long bookId) {
    Optional<Book> book = bookRepository.findById(bookId);
    if (book.isPresent()) {
        return ResponseEntity.ok().body(book.get());
    } else {
        return ResponseEntity.notFound().build();
    }
}

To update an existing book, we can use the save() method again:

@PutMapping("/{id}")
public ResponseEntity<Book> updateBook(@PathVariable(value = "id") Long bookId,
                                        @RequestBody Book bookDetails) {
    Optional<Book> optionalBook = bookRepository.findById(bookId);
    if (optionalBook.isPresent()) {
        Book book = optionalBook.get();
        book.setTitle(bookDetails.getTitle());
        book.setAuthor(bookDetails.getAuthor());
        book.setDescription(bookDetails.getDescription());
        book.setPrice(bookDetails.getPrice());
        Book updatedBook = bookRepository.save(book);
        return ResponseEntity.ok().body(updatedBook);
    } else {
        return ResponseEntity.notFound().build();
    }
}

And finally, to delete a book from the database, we can use the deleteById() method:

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteBook(@PathVariable(value = "id") Long bookId) {
    bookRepository.deleteById(bookId);
    return ResponseEntity.noContent().build();
}

And that’s it! With these changes, our RESTful API now supports CRUD operations using a MySQL database.

In conclusion, Spring Boot provides a convenient and powerful framework for building RESTful APIs. With the help of Spring Data JPA, we can easily integrate our API with a database and perform common database operations with minimal code. By following the steps outlined in this guide, you should now have a solid understanding of how to build a Spring Boot RESTful API with MySQL support.

Here is the complete BookController class that supports CRUD operations with MySQL database:

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

    @Autowired
    private BookRepository bookRepository;

    @GetMapping
    public List<Book> getAllBooks() {
        return bookRepository.findAll();
    }

    @GetMapping("/{id}")
    public ResponseEntity<Book> getBookById(@PathVariable(value = "id") Long bookId) {
        Optional<Book> book = bookRepository.findById(bookId);
        if (book.isPresent()) {
            return ResponseEntity.ok().body(book.get());
        } else {
            return ResponseEntity.notFound().build();
        }
    }

    @PostMapping
    public Book createBook(@RequestBody Book book) {
        return bookRepository.save(book);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Book> updateBook(@PathVariable(value = "id") Long bookId,
                                            @RequestBody Book bookDetails) {
        Optional<Book> optionalBook = bookRepository.findById(bookId);
        if (optionalBook.isPresent()) {
            Book book = optionalBook.get();
            book.setTitle(bookDetails.getTitle());
            book.setAuthor(bookDetails.getAuthor());
            book.setDescription(bookDetails.getDescription());
            book.setPrice(bookDetails.getPrice());
            Book updatedBook = bookRepository.save(book);
            return ResponseEntity.ok().body(updatedBook);
        } else {
            return ResponseEntity.notFound().build();
        }
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteBook(@PathVariable(value = "id") Long bookId) {
        bookRepository.deleteById(bookId);
        return ResponseEntity.noContent().build();
    }
}

MySQL database schema

If you want to create the database and the book table manually, then use the following schema.

Here is the MySQL database schema for the books table:

CREATE TABLE `books` (
  `id` int NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `author` varchar(255) NOT NULL,
  `description` text,
  `price` decimal(10,2) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

You can import this schema into your MySQL database using any MySQL client like MySQL Workbench or phpMyAdmin. Alternatively, you can also run this SQL script from the command line using the mysql command-line tool:

mysql -u your_username -p your_database_name < books_schema.sql

Just make sure to replace your_username and your_database_name with your actual MySQL username and database name.

Spring Boot REST API Using MariaDB

Here is how you can modify the application.properties file to use MariaDB instead of MySQL:

spring.datasource.url=jdbc:mariadb://localhost:3306/library
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect

And here is the complete BookController class that supports CRUD operations with MariaDB:

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

    @Autowired
    private BookRepository bookRepository;

    @GetMapping
    public List<Book> getAllBooks() {
        return bookRepository.findAll();
    }

    @GetMapping("/{id}")
    public ResponseEntity<Book> getBookById(@PathVariable(value = "id") Long bookId) {
        Optional<Book> book = bookRepository.findById(bookId);
        if (book.isPresent()) {
            return ResponseEntity.ok().body(book.get());
        } else {
            return ResponseEntity.notFound().build();
        }
    }

    @PostMapping
    public Book createBook(@RequestBody Book book) {
        return bookRepository.save(book);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Book> updateBook(@PathVariable(value = "id") Long bookId,
                                            @RequestBody Book bookDetails) {
        Optional<Book> optionalBook = bookRepository.findById(bookId);
        if (optionalBook.isPresent()) {
            Book book = optionalBook.get();
            book.setTitle(bookDetails.getTitle());
            book.setAuthor(bookDetails.getAuthor());
            book.setDescription(bookDetails.getDescription());
            book.setPrice(bookDetails.getPrice());
            Book updatedBook = bookRepository.save(book);
            return ResponseEntity.ok().body(updatedBook);
        } else {
            return ResponseEntity.notFound().build();
        }
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteBook(@PathVariable(value = "id") Long bookId) {
        bookRepository.deleteById(bookId);
        return ResponseEntity.noContent().build();
    }
}

We will need to add the MariaDB connector dependency to our build.gradle file. Add the following line to the dependencies section:

dependencies {
    implementation 'org.mariadb.jdbc:mariadb-java-client:2.7.4'
    // other dependencies...
}

And also make sure to update the BookRepository interface to extend JpaRepository<Book, Long> instead of CrudRepository<Book, Long>:

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

With these changes, you should be able to use MariaDB instead of MySQL in your Spring Boot application.

Spring Boot REST API Using Oracle

Here is how you can modify the application.properties file to use the Oracle database:

spring.datasource.url=jdbc:oracle:thin:@localhost:1521:ORCL
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver

You will need to replace your_username and your_password with your actual Oracle database username and password. You will also need to update the spring.datasource.url property to reflect your specific Oracle database connection details.

To connect to an Oracle database using Spring Boot, you will need to add the Oracle JDBC driver as a dependency in your build.gradle file.

dependencies {
    implementation 'com.oracle.database.jdbc:ojdbc10:19.3.0.0'
   // other dependencies...
}

In this example, we are using version 19.3.0.0 of the Oracle JDBC driver. You may need to update this version number depending on the version of Oracle that you are using.

Once you have added these properties to your application.properties and the build.gradle files, Spring Boot should be able to connect to your Oracle database.

Conclusion

In this tutorial, we’ve learned how to build a RESTful API using Spring Boot. We started by creating a new Spring Boot project using the Spring Initializr, and then we wrote code to define our data model, repository, and controller. We also configured our application to use an in-memory database and expose our API over HTTP.

Building a RESTful API with Spring Boot is a powerful way to build scalable and maintainable web applications. By following the steps in this tutorial, you should now have a solid foundation for building your own APIs using Spring Boot.

However, this tutorial only scratches the surface of what is possible with Spring Boot. There are many other features and capabilities that we haven’t covered, such as security, testing, and deployment. I encourage you to explore the Spring Boot documentation and continue learning about this powerful framework.

Also, see the example code JavaExamples_NoteArena in our GitHub repository. See complete examples in our GitHub repositories.

Follow us on social media
Follow Author