The existsById method provided by the Spring Data JPA allows us to check if a record exists by its ID in the Spring Data JPA Repository database table. We can use exists by id in JPA Spring Boot by creating a JPA Repository interface to use its query method existsById(ID id) in the Spring Boot application. This method returns a boolean indicating whether an entity with the provided ID exists in the database table. In this topic, we will learn how to use exists by id in the JPA Spring Boot application.
Use Exists By Id in JPA Spring Boot
These are the following steps to use exists by id in JPA Spring Boot:
1. Create a JPA Repository
Create a repository interface by extending JpaRepository in the Spring Boot.
Example
public interface OrderRepository extends JpaRepository<OrderDetail, Long> {
}
2. Use existsById Method
To use the existsById query method we need to create Service in the Spring Boot.
Example
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderRepository orderRepo;
@Override
public boolean orderExists(Long orderId) {
return orderRepo.existsById(orderId);
}
}
Why Use existsById in JPA Repository?
- Performance Optimization: The existsById only checks if a record exists, without retrieving the full entity, saving time and resources.
- Simplify Conditional Logic: This allows you to verify an entity’s existence without running complex queries.
- Error Prevention: This prevents EntityNotFoundException by checking existence before performing operations like update or delete.
Step-by-step Guide to Use Exists By Id in JPA Spring Boot
Let’s create a Spring Boot Application step-by-step guide for using exists by ID in JPA Spring Boot. We will create an example of OrderDetail, where we can delete a record only if it exists using the existById query method of Spring Data JPA with the help API endpoint.
These are the following steps:
- Create a Spring Boot Project
- Setup in the IDE
- Configure H2 Database
- Create a JPA Entity
- Create a Repository Interface
- Create a Service Interface
- Implement the Service Interface
- Create a Controller
- Run the Spring Boot Application
1. Create a Spring Boot Project
We are creating a Spring Boot Project from the web tool Spring Initializr. By Providing details for the project and select the following Maven dependencies:
- Spring Web
- Spring Data JPA
- H2 Database
- Lombok
2. Setup in the IDE
We use Eclipse IDE to set up and configure the created Spring Boot Project. You can use other IDE to set up and configure the Spring Boot project.
Project Structure of Spring Boot
This image shows the project structure of Spring Boot in Eclipse IDE.
Maven Dependency
This is the complete Maven dependencies for this application which will be implemented exists by id in JPA Spring Boot.
pom.xml
<?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.0</version>
<relativePath />
<!-- lookup parent from repository -->
</parent>
<groupId>com.springjava</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.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-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</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>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
3. Configure H2 Database
We are going to configure the H2 database connection in the application.properties file.
application.properties
#H2 Database Configuration
spring.datasource.url=jdbc:h2:mem:test
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.h2.console.enabled=true
4. Create a JPA Entity
Let’s create a JPA Entity class. For example, consider an OrderDetail entity and use Lombok for generating setter and getter methods, a constructor, etc.
OrderDetail.java
package com.springjava.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
@Data
@Entity
public class OrderDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String productName;
private double price;
}
5. Create a Repository Interface
Create a repository interface for the OrderDetail JPA Entity class. This interface extends the JpaRepository interface and performs persistence operations like saveAll, deleteById, and existsById on the database table.
OrderRepository.java
package com.springjava.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.springjava.entity.OrderDetail;
public interface OrderRepository extends JpaRepository<OrderDetail, Long> {
}
6. Create a Service Interface
Create a Service interface OrderService with some method declaration.
OrderService.java
package com.springjava.service;
import java.util.List;
import com.springjava.entity.OrderDetail;
public interface OrderService {
void saveAll(List<OrderDetail> orderList);
void deleteOrderIfExists(Long orderId);
}
7. Implement the Service Interface
Implement the OrderService interface in the OrderServiceImpl class. This class is annotated with @Service annotation, where we inject OrderRepository to call all its methods(saveAll(), existsById() and deleteById()).
OrderServiceImpl.java
package com.springjava.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.springjava.entity.OrderDetail;
import com.springjava.repository.OrderRepository;
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderRepository orderRepo;
@Override
public void saveAll(List<OrderDetail> orderList) {
orderRepo.saveAll(orderList);
}
@Override
public void deleteOrderIfExists(Long orderId) {
if (orderRepo.existsById(orderId)) {
orderRepo.deleteById(orderId);
} else {
throw new IllegalArgumentException("OrderDetail with ID " + orderId + " does not exist.");
}
}
}
- existsById: This checks if the order exists before proceeding to delete.
- Exception Handling: This Throws an exception if the order doesn’t exist, improving error handling.
8. Create a Controller
Create a controller class OrderController. This is annotated with @RestController to make this class a RestController.
OrderController.java
package com.springjava.controller;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.springjava.entity.OrderDetail;
import com.springjava.service.OrderService;
@RestController
@RequestMapping("/api/order")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/save-all")
public ResponseEntity<?> save(@RequestBody List<OrderDetail> orderList) {
Map<String, Object> respOrder = new LinkedHashMap<String, Object>();
orderService.saveAll(orderList);
respOrder.put("status", 1);
respOrder.put("message", "Record is Saved Successfully!");
return new ResponseEntity<>(respOrder, HttpStatus.CREATED);
}
@DeleteMapping("/delete/{id}")
public ResponseEntity<?> deleteOrder(@PathVariable Long id) {
Map<String, Object> respOrder = new LinkedHashMap<String, Object>();
try {
orderService.deleteOrderIfExists(id);
respOrder.put("status", 1);
respOrder.put("message", "OrderDetail with ID " + id + " has been deleted.");
return new ResponseEntity<>(respOrder, HttpStatus.OK);
} catch (IllegalArgumentException e) {
respOrder.clear();
respOrder.put("status", 0);
respOrder.put("message", e.getMessage());
return new ResponseEntity<>(respOrder, HttpStatus.NOT_FOUND);
}
}
}
- save(): This saves the list of OrderDetail and returns a 200 OK message response.
- deleteOrder(): This deletes an order only if it exists, and returns a 404 Not Found message if it doesn’t.
9. Run the Spring Boot Application
Right-click this Spring Boot application on the DemoApplication.java, then click Run As and select Java Application.
H2 Database Console
To check the H2 database console use the URL http://localhost:[server_port]/h2-console.
JSON Array
We are creating a sample JSON Array to test the API http://localhost:8080/api/order/save-all.
[
{
"productName": "Demo",
"price": "200"
},
{
"productName": "Abc",
"price": "300"
}
]
POST: http://localhost:8080/api/webseries/save-all
GET: http://localhost:8080/api/order/delete/1
Benefits of Using existsById in JPA Repository
- Improved Performance: The method avoids loading the entire entity, saving resources for cases requiring only a check.
- Error Handling: This method allows us to handle cases where an entity is missing without throwing an exception.
- Simplified Code: This method syntax reduces boilerplate code and simplifies conditional checks.
Best Practices for Using existsById
- Use Before Deletion or Update: This method checks entity existence before modifying or deleting, preventing runtime errors.
- Integrate in Business Logic: This method adds the existence check in the service layer to ensure that controllers don’t perform business logic.
- Handle Non-Existence Gracefully: This method considers returning custom error messages or codes when the entity doesn’t exist.
Conclusion
The existsById query method in Spring Data JPA is a powerful and efficient way to check if a record exists without loading the full entity. By incorporating existsById into our JPA Repository in Spring Boot, we can improve performance, simplify code, and ensure better error handling in our application.