Spring Data REST example in Spring Boot

In this tutorial, we’re gonna build a Spring Data REST example in Spring Boot CRUD REST API with Maven that uses Spring Data JPA to interact with H2 database without having to manually implement controller and handling HTTP requests. You’ll know:

  • How to configure Spring Data REST, JPA, Hibernate to work with Database
  • How to define Data Models and Repository interfaces
  • Way to use Spring Data JPA to interact with H2 Database
  • How to check CRUD operations with Postman

More Practice:
Spring JPA @Query example
JPA Repository query example | Derived Query
JPA Native Query example
Spring Boot Security Login example with JWT and H2 Database
Spring Boot Rest XML example
Spring Boot + GraphQL example
Spring Boot Multipart File upload example
– Documentation: Spring Boot + Swagger 3 example (with OpenAPI 3)
– Caching: Spring Boot Redis Cache example
– Testing: Spring Boot Unit Test for JPA Repository

Associations:
Spring Boot One To One example with JPA, Hibernate
Spring Boot One To Many example with JPA, Hibernate
Spring Boot Many to Many example with JPA, Hibernate


Spring Data REST vs Spring Data JPA

Spring Data REST and Spring Data JPA are both projects within the larger Spring Data umbrella, and they serve different purposes in the context of building data-centric applications with Spring.

Spring Data JPA is often used in conjunction with Spring Data REST. Spring Data REST can automatically expose Spring Data JPA repositories as RESTful APIs. This means that once you’ve defined your JPA entities and repositories using Spring Data JPA, you can use Spring Data REST to expose those repositories as RESTful services without having to write additional controller code.

Spring Data JPA

Purpose: Spring Data JPA simplifies the development of data access layers by providing a set of abstractions and utilities for working with JPA (Java Persistence API) implementations.
Features:

  • Automatic CRUD (Create, Read, Update, Delete) repository generation based on JPA entities.
  • Query methods derived from method names in repository interfaces.
  • Custom queries using JPQL (Java Persistence Query Language) or native SQL.
  • Pagination, sorting, and other common data access operations are supported.

Usage: If you need a data access layer for working with a relational database and want to leverage JPA for that purpose, Spring Data JPA is a good choice. It provides a higher-level abstraction over JPA, making it easier to work with databases in a Spring application.

For more example, kindly visit:

Spring Data REST

Purpose: Spring Data REST builds on top of Spring Data repositories and exposes them as RESTful services. It automates the process of exposing JPA repositories as RESTful endpoints.
Features:

  • Automatic generation of RESTful APIs for Spring Data repositories.
  • Supports CRUD operations over HTTP (GET, POST, PUT, DELETE) for entities.
  • Follows HATEOAS (Hypermedia as the Engine of Application State) principles, providing discoverable APIs.
  • Customization of endpoints and response formats.

Usage: Spring Data REST is used when you want to quickly expose your Spring Data JPA repositories as RESTful services without having to manually implement controllers and handling HTTP requests. It’s useful for rapidly building APIs over your data model.

Overview of Spring Data REST example

We will build a Spring Boot Data REST example for a Tutorial application in that:

  • Each Tutorial has id, title, description, published status.
  • We can create, retrieve, update, delete Tutorials.
  • We have custom finder methods such as find by published status or by title.

These are REST APIs that we provide:

Methods Urls Actions
POST /api/tutorials create new Tutorial
GET /api/tutorials retrieve all Tutorials
GET /api/tutorials/:id retrieve a Tutorial by :id
PUT /api/tutorials/:id update a Tutorial by :id
DELETE /api/tutorials/:id delete a Tutorial by :id

We also have APIs for:
– find all published/unpublished Tutorials:
GET /api/tutorials/search/findByPublished?published=[status]

– find all Tutorials which title contains keyword
/api/tutorials/search/findByTitleContainingIgnoreCase?title=[keyword]

Technology

  • Java 17 / 11 / 8
  • Spring Boot 3 / 2 (with Spring Data REST, Spring Data JPA)
  • H2 Database
  • Maven

Project Structure

spring-data-rest-example-project

Let me explain it briefly.

Tutorial data model class corresponds to entity and table tutorials.
TutorialRepository is an interface that extends JpaRepository for CRUD methods and custom finder methods.
– Configuration for Spring Data REST, Datasource, JPA & Hibernate in application.properties.
pom.xml contains dependencies for Spring Boot and H2.

We can improve the example by adding Comments for each Tutorial. It is the One-to-Many Relationship and I write a tutorial for this at:
Spring Boot One To Many example with JPA, Hibernate

Or add Tags with Many-to-Many Relationship:
Spring Boot Many to Many example with JPA, Hibernate

Create & Setup Spring Boot project

Use Spring web tool or your development tool (Spring Tool Suite, Eclipse, Intellij) to create a Spring Boot project.

Then open pom.xml and add these 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-data-rest</artifactId>
</dependency>

<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
	<scope>runtime</scope>
</dependency>

Configure Spring Data REST, JPA, h2, Hibernate

Under src/main/resources folder, open application.properties and write these lines.

spring.data.rest.basePath=api

spring.h2.console.enabled=true
# default path: h2-console
spring.h2.console.path=/h2-ui
 
spring.datasource.url=jdbc:h2:file:./testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
 
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto= update
  • spring.data.rest.basePath: the root URI for Spring Data REST
  • spring.datasource.url: jdbc:h2:mem:[database-name] for In-memory database and jdbc:h2:file:[path/database-name] for disk-based database.
  • spring.datasource.username & spring.datasource.password properties are the same as your database installation.
  • Spring Boot uses Hibernate for JPA implementation, we configure H2Dialect for H2 Database
  • spring.jpa.hibernate.ddl-auto is used for database initialization. We set the value to update value so that a table will be created in the database automatically corresponding to defined data model. Any change to the model will also trigger an update to the table. For production, this property should be validate.
  • spring.h2.console.enabled=true tells the Spring to start H2 Database administration tool and you can access this tool on the browser: http://localhost:8080/h2-console.
  • spring.h2.console.path=/h2-ui is for H2 console’s url, so the default url http://localhost:8080/h2-console will change to http://localhost:8080/h2-ui.

You can also alter the following Spring Data REST properties (starting with spring.data.rest.):
defaultPageSize: change the default for the number of items served in a single page.
maxPageSize: change the maximum number of items in a single page.
pageParamName: change the name of the query parameter for selecting pages.
limitParamName: change the name of the query parameter for the number of items to show in a page.
sortParamName: change the name of the query parameter for sorting.
defaultMediaType: change the default media type to use when none is specified.
returnBodyOnCreate: change whether a body should be returned when creating a new entity.
returnBodyOnUpdate: change whether a body should be returned when updating an entity.

Define Data Model

Our Data model is Tutorial with four fields: id, title, description, published.
In model package, we define Tutorial class.

model/Tutorial.java

package com.bezkoder.spring.data.rest.model;

import jakarta.persistence.*;

@Entity
@Table(name = "tutorials")
public class Tutorial {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;

  @Column(name = "title")
  private String title;

  @Column(name = "description")
  private String description;

  @Column(name = "published")
  private boolean published;

  public Tutorial() {

  }

  public Tutorial(String title, String description, boolean published) {
    this.title = title;
    this.description = description;
    this.published = published;
  }

  // getters and setters...

}

@Entity annotation indicates that the class is a persistent Java class.
@Table annotation provides the table that maps this entity.
@Id annotation is for the primary key.
@GeneratedValue annotation is used to define generation strategy for the primary key. GenerationType.AUTO means Auto Increment field.
@Column annotation is used to define the column in database that maps annotated field.

Create Repository Interface

Let’s create a repository to interact with Tutorials from the database.
In repository package, create TutorialRepository interface that extends JpaRepository.

repository/TutorialRepository.java

package com.bezkoder.spring.data.rest.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.web.bind.annotation.CrossOrigin;

import com.bezkoder.spring.data.rest.model.Tutorial;

@RepositoryRestResource(path="tutorials")
public interface TutorialRepository extends JpaRepository<Tutorial, Long> {
  List<Tutorial> findByPublished(boolean published);

  List<Tutorial> findByTitleContainingIgnoreCase(String title);
}

To expose the repository as a RESTful resource, you annotate the repository interface with @RepositoryRestResource. This annotation allows you to customize the RESTful endpoints and behavior, and path defines the base URI path for the resource.

We also define custom finder methods:
findByPublished(): returns all Tutorials with published having value as input published.
findByTitleContaining(): returns all Tutorials which title contains input title.

The implementation is plugged in by Spring Data JPA automatically.

More Derived queries at:
JPA Repository query example in Spring Boot

Custom query with @Query annotation:
Spring JPA @Query example: Custom query in Spring Boot

You can modify this Repository:
– to work with Pagination, the instruction can be found at:
Spring Boot Pagination & Filter example | Spring JPA, Pageable
– or to sort/order by multiple fields with the tutorial:
Spring Data JPA Sort/Order by multiple Columns | Spring Boot

You also find way to write Unit Test for this JPA Repository at:
Spring Boot Unit Test for JPA Repository with @DataJpaTest

Configure CORS in Spring Data REST

We add a @CrossOrigin annotation to the repository interface to enable CORS for the whole TutorialRepository repository.

By default, @CrossOrigin allows all origins and HTTP methods.

repository/TutorialRepository.java

// ...
import org.springframework.web.bind.annotation.CrossOrigin;

@CrossOrigin
@RepositoryRestResource(path="tutorials")
public interface TutorialRepository extends JpaRepository<Tutorial, Long> {
  // ...
}

We can provide one origin, restricted to several HTTP methods with a specific max age.

@CrossOrigin(origins = "http://yourdomain.example",
  methods = { RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE },
  maxAge = 3600)
@RepositoryRestResource(path="tutorials")
public interface TutorialRepository extends JpaRepository<Tutorial, Long> {
  // ...
}

Run & Test

Run Spring Boot application with command: mvn spring-boot:run.

tutorials table will be automatically generated in Database.

Let’s open H2 console with url: http://localhost:8080/h2-ui:

– For In-memory database:

spring-data-rest-example-h2-console-in-memory

– For on Disk database:

spring-data-rest-example-h2-console-on-disk

Click on Connect button, then check H2 database, you can see things like this:

spring-data-rest-example-database-table

Create some Tutorials:

spring-data-rest-example-crud-create

Retrieve all Tutorials:

spring-data-rest-example-crud-retrieve

Retrieve a Tutorial by Id:

spring-data-rest-example-crud-retrieve-one

Update some Tutorials:

spring-data-rest-example-crud-update

The table data is changed:

spring-data-rest-example-crud-update-database

Spring Data REST to filter all published Tutorials:

spring-data-rest-filter-example

Find all Tutorials which title contains string ‘data’:

spring-data-rest-search-example

Delete a Tutorial:

spring-data-rest-example-crud-delete

Check database and it has been already deleted.

spring-data-rest-example-crud-delete-table

Conclusion

Today we’ve built a Spring Boot Rest CRUD API using Spring Data REST example and make Spring Data JPA work with H2 Database.

We also see that JpaRepository supports a great way to make CRUD operations and custom finder methods without need of boilerplate code.

Happy learning! See you again.

Further Reading

Fullstack CRUD App:
Spring Boot Thymeleaf example
Vue + Spring Boot example
Angular 8 + Spring Boot example
Angular 10 + Spring Boot example
Angular 11 + Spring Boot example
Angular 12 + Spring Boot example
Angular 13 + Spring Boot example
Angular 14 + Spring Boot example
Angular 15 + Spring Boot example
Angular 16 + Spring Boot example
React + Spring Boot example

If you want to add Pagination to this Spring project, you can find the instruction at:
Spring Boot Pagination & Filter example | Spring JPA, Pageable

To sort/order by multiple fields:
Spring Data JPA Sort/Order by multiple Columns | Spring Boot

Or way to write Unit Test:
Spring Boot Unit Test for JPA Repository

We can improve the example by adding Comments for each Tutorial. It is the One-to-Many Relationship and I write a tutorial for this at:
Spring Boot One To Many example with JPA, Hibernate

Or add Tags with Many-to-Many Relationship:
Spring Boot Many to Many example with JPA, Hibernate

Source Code

You can find the complete source code for this tutorial on Github.

With Rest Controller: Spring Boot JPA + H2 example: Build a CRUD Rest APIs
Or APIs with GraphQL:Spring Boot + GraphQL example

More JPA queries at:
Spring JPA @Query example
JPA Repository query example | Derived Query
JPA Native Query example

Validation:
Validate Request Body in Spring Boot

Reactive with R2DBC:
Spring Boot R2DBC + H2 example

Documentation: Spring Boot + Swagger 3 example (with OpenAPI 3)
Caching: Spring Boot Redis Cache example