Overview
Spring Data JPA query methods are the most powerful methods, we can create query methods to select records from the database without writing SQL queries. Behind the scenes, Spring Data JPA will create SQL queries based on the query method and execute the query for us.We can create query methods for the repository using Entity fields and creating query methods is also called finder methods ( findBy, findAll …)
public interface UserRepository extends Repository<User, Long> {
List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}
Supported keywords inside method names
Rules for Creating Query Methods
1. Creating Spring Boot Project
Spring Boot provides a web tool called https://start.spring.io to bootstrap an application quickly. Just go to https://start.spring.io and generate a new spring boot project.Use the below details in the Spring boot creation:
Project Name: spring-data-jpa-course
Project Type: Maven
Choose dependencies: Spring Data JPA, MySQL Driver, Lombok
Package name: net.javaguides.springboot
Use the below details in the Spring boot creation:
Project Name: spring-data-jpa-course
Project Type: Maven
Choose dependencies: Spring Data JPA, MySQL Driver, Lombok
Package name: net.javaguides.springboot
2. Maven Dependencies
Here is the complete pom.xml for your reference:
<?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.0.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>net.javaguides</groupId>
<artifactId>spring-data-jpa-course</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-data-jpa-course</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>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</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>
</plugin>
</plugins>
</build>
</project>
3. Configure MySQL database
Let's use the MySQL database to store and retrieve the data in this example and we gonna use Hibernate properties to create and drop tables.Open the application.properties file and add the following configuration to it:spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
spring.datasource.username=root
spring.datasource.password=Mysql@123
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto = create-drop
Make sure that you will create a demo database before running the Spring boot application.Also, change the MySQL username and password as per your MySQL installation on your machine.
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
spring.datasource.username=root
spring.datasource.password=Mysql@123
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto = create-drop
4. Create JPA Entity - Product.java
Let's create an entity package inside a base package "net.javaguides.springboot". Within the entity package, create a Product class with the following content:import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Table(
name = "products",
schema = "ecommerce",
uniqueConstraints = {
@UniqueConstraint(
name = "sku_unique",
columnNames = "stock_keeping_unit"
)
}
)
public class Product {
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "product_generator"
)
@SequenceGenerator(
name = "product_generator",
sequenceName = "product_sequence_name",
allocationSize = 1
)
private Long id;
@Column(name = "stock_keeping_unit", nullable = false)
private String sku;
@Column(nullable = false)
private String name;
private String description;
private BigDecimal price;
private boolean active;
private String imageUrl;
@CreationTimestamp
private LocalDateTime dateCreated;
@UpdateTimestamp
private LocalDateTime lastUpdated;
}
import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Table(
name = "products",
schema = "ecommerce",
uniqueConstraints = {
@UniqueConstraint(
name = "sku_unique",
columnNames = "stock_keeping_unit"
)
}
)
public class Product {
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "product_generator"
)
@SequenceGenerator(
name = "product_generator",
sequenceName = "product_sequence_name",
allocationSize = 1
)
private Long id;
@Column(name = "stock_keeping_unit", nullable = false)
private String sku;
@Column(nullable = false)
private String name;
private String description;
private BigDecimal price;
private boolean active;
private String imageUrl;
@CreationTimestamp
private LocalDateTime dateCreated;
@UpdateTimestamp
private LocalDateTime lastUpdated;
}
Note that we are using Lombok annotations to reduce the boilerplate code.
5. Create Spring Data JPA Repository
The next thing we’re gonna do is to create a repository to access Product entity data from the database.The JpaRepository interface defines methods for all the CRUD operations on the entity, and a default implementation of the JpaRepository called SimpleJpaRepository.
Let's create a repository package inside a base package "net.javaguides.springdatarest".
Within the repository package, create a ProductRepository interface with the following content:
import com.springdatajpa.springboot.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
public interface ProductRepository extends JpaRepository<Product, Long> {
/**
* Returns the found product entry by using its name as search
* criteria. If no product entry is found, this method
* returns null.
*/
public Product findByName(String name);
/**
* Returns an Optional which contains the found product
* entry by using its id as search criteria. If no product entry
* is found, this method returns an empty Optional.
*/
Optional<Product> findById(Long id);
/**
* Returns the found list of product entries whose name or description is given
* as a method parameters. If no product entries is found, this method
* returns an empty list.
*/
List<Product> findByNameOrDescription(String name, String description);
/**
* Returns the found list of product entries whose name and description is given
* as a method parameters. If no product entries is found, this method
* returns an empty list.
*/
List<Product> findByNameAndDescription(String name, String description);
/**
* Return the distinct product entry whose name is given as a method parameter
* If no product entry is found, this method returns null.
*/
Product findDistinctByName(String name);
/**
* Return the products whose price is greater than given price as method parameter
* @param price
* @return
*/
List<Product> findByPriceGreaterThan(BigDecimal price);
/**
* Return the products whose price is less than given price as method parameter
* @param price
* @return
*/
List<Product> findByPriceLessThan(BigDecimal price);
/**
* Return the filtered the product records that match the given text
* @param name
* @return
*/
List<Product> findByNameContaining(String name);
/**
* Return products based on SQL like condition
* @param name
* @return
*/
List<Product> findByNameLike(String name);
/**
* Returns a products whose price between start price and end price
* @param startPrice
* @param endPrice
* @return
*/
List<Product> findByPriceBetween(BigDecimal startPrice, BigDecimal endPrice);
/**
* Returns a products whose dateCreated between start date and end date
* @param startDate
* @param endDate
* @return
*/
List<Product> findByDateCreatedBetween(LocalDateTime startDate, LocalDateTime endDate);
}
import com.springdatajpa.springboot.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
public interface ProductRepository extends JpaRepository<Product, Long> {
/**
* Returns the found product entry by using its name as search
* criteria. If no product entry is found, this method
* returns null.
*/
public Product findByName(String name);
/**
* Returns an Optional which contains the found product
* entry by using its id as search criteria. If no product entry
* is found, this method returns an empty Optional.
*/
Optional<Product> findById(Long id);
/**
* Returns the found list of product entries whose name or description is given
* as a method parameters. If no product entries is found, this method
* returns an empty list.
*/
List<Product> findByNameOrDescription(String name, String description);
/**
* Returns the found list of product entries whose name and description is given
* as a method parameters. If no product entries is found, this method
* returns an empty list.
*/
List<Product> findByNameAndDescription(String name, String description);
/**
* Return the distinct product entry whose name is given as a method parameter
* If no product entry is found, this method returns null.
*/
Product findDistinctByName(String name);
/**
* Return the products whose price is greater than given price as method parameter
* @param price
* @return
*/
List<Product> findByPriceGreaterThan(BigDecimal price);
/**
* Return the products whose price is less than given price as method parameter
* @param price
* @return
*/
List<Product> findByPriceLessThan(BigDecimal price);
/**
* Return the filtered the product records that match the given text
* @param name
* @return
*/
List<Product> findByNameContaining(String name);
/**
* Return products based on SQL like condition
* @param name
* @return
*/
List<Product> findByNameLike(String name);
/**
* Returns a products whose price between start price and end price
* @param startPrice
* @param endPrice
* @return
*/
List<Product> findByPriceBetween(BigDecimal startPrice, BigDecimal endPrice);
/**
* Returns a products whose dateCreated between start date and end date
* @param startDate
* @param endDate
* @return
*/
List<Product> findByDateCreatedBetween(LocalDateTime startDate, LocalDateTime endDate);
}
Let's understand the query methods from the above ProductRepository interface.
Query method to find or retrieve a product by name:
/**
* Returns the found product entry by using its name as search
* criteria. If no product entry is found, this method
* returns null.
*/
public Product findByName(String name);
/**
* Returns the found product entry by using its name as search
* criteria. If no product entry is found, this method
* returns null.
*/
public Product findByName(String name);
Query method to find or retrieve a product by id:
/**
* Returns an Optional which contains the found product
* entry by using its id as search criteria. If no product entry
* is found, this method returns an empty Optional.
*/
Optional<Product> findById(Long id);
Query method to find or retrieve a product by name or description:
/**
* Returns the found list of product entries whose name or description is given
* as a method parameters. If no product entries is found, this method
* returns an empty list.
*/
List<Product> findByNameOrDescription(String name, String description);
Query method to find or retrieve a product by name and description:
/**
* Returns the found list of product entries whose name and description is given
* as a method parameters. If no product entries is found, this method
* returns an empty list.
*/
List<Product> findByNameAndDescription(String name, String description);
Query method to find or retrieve a unique product by name:
/**
* Return the distinct product entry whose name is given as a method parameter
* If no product entry is found, this method returns null.
*/
Product findDistinctByName(String name);
Query method to find or retrieve products whose price is greater than the given price as a method parameter:
Query method to find or retrieve products whose price is less than given price as a method parameter:/** * Return the products whose price is greater than given price as method parameter * @param price * @return */ List<Product> findByPriceGreaterThan(BigDecimal price);
/**
* Return the products whose price is less than given price as method parameter
* @param price
* @return
*/
List<Product> findByPriceLessThan(BigDecimal price);
Query method to find or retrieve filtered products that match the given text ( contains check): /**
* Return the filtered the product records that match the given text
* @param name
* @return
*/
List<Product> findByNameContaining(String name);
Query method to find or retrieve products for a specified pattern in a column ( SQL LIKE condition): /**
* Return products based on SQL like condition
* @param name
* @return
*/
List<Product> findByNameLike(String name);
Query method to find or retrieve products based on the price range ( start price and end price): /**
* Returns a products whose price between start price and end price
* @param startPrice
* @param endPrice
* @return
*/
List<Product> findByPriceBetween(BigDecimal startPrice, BigDecimal endPrice);
6. Test Spring Data JPA Query Methods
Now let's write a JUnit test case to test above all Spring Data JPA query methods:
import com.springdatajpa.springboot.entity.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.List;
import java.util.Optional;
@SpringBootTest
public class QueryMethodsTest {
@Autowired
private ProductRepository productRepository;
@Test
void findByNameMethod(){
Product product = productRepository.findByName("product 2");
System.out.println(product.getId());
System.out.println(product.getName());
System.out.println(product.getDescription());
}
@Test
void findByIdMethod(){
Product product = productRepository.findById(1L).get();
System.out.println(product.getId());
System.out.println(product.getName());
System.out.println(product.getDescription());
}
@Test
void findByNameOrDescriptionMethod(){
List<Product> products = productRepository.findByNameOrDescription("product 1",
"product 1 description");
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
@Test
void findByNameAndDescriptionMethod(){
List<Product> products = productRepository.findByNameAndDescription("product 1",
"product 1 description");
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
@Test
void findDistinctByNameMethod(){
Product product = productRepository.findDistinctByName("product 1");
System.out.println(product.getId());
System.out.println(product.getName());
System.out.println(product.getDescription());
}
@Test
void findByPriceGreaterThanMethod(){
List<Product> products = productRepository.findByPriceGreaterThan(new BigDecimal(100));
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
@Test
void findByPriceLessThanMethod(){
List<Product> products = productRepository.findByPriceLessThan(new BigDecimal(200));
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
@Test
void findByNameContainingMethod(){
List<Product> products = productRepository.findByNameContaining("product 1");
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
@Test
void findByNameLikeMethod(){
List<Product> products = productRepository.findByNameLike("product 1");
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
@Test
void findByPriceBetweenMethod(){
List<Product> products = productRepository.findByPriceBetween(
new BigDecimal(100), new BigDecimal(300)
);
products.forEach((p) ->{
System.out.println(p.getId());
System.out.println(p.getName());
});
}
@Test
void findByDateCreatedBetweenMethod(){
// start date
LocalDateTime startDate = LocalDateTime.of(2022,02,13,17,48,33);
// end date
LocalDateTime endDate = LocalDateTime.of(2022,02,13,18,15,21);
List<Product> products = productRepository.findByDateCreatedBetween(startDate, endDate);
products.forEach((p) ->{
System.out.println(p.getId());
System.out.println(p.getName());
});
}
}
Output:
JUnit Test for findByName Query Method:
@Test
void findByNameMethod(){
Product product = productRepository.findByName("product 2");
System.out.println(product.getId());
System.out.println(product.getName());
System.out.println(product.getDescription());
}
JUnit Test for findById Query Method:
@Test
void findByIdMethod(){
Product product = productRepository.findById(1L).get();
System.out.println(product.getId());
System.out.println(product.getName());
System.out.println(product.getDescription());
}
JUnit Test for findByNameOrDescription Query Method:
@Test
void findByNameOrDescriptionMethod(){
List<Product> products = productRepository.findByNameOrDescription("product 1",
"product 1 description");
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
JUnit Test for findByNameAndDescription Query Method:
@Test
void findByNameAndDescriptionMethod(){
List<Product> products = productRepository.findByNameAndDescription("product 1",
"product 1 description");
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
JUnit Test for findDistinctByName Query Method:
@Test
void findDistinctByNameMethod(){
Product product = productRepository.findDistinctByName("product 1");
System.out.println(product.getId());
System.out.println(product.getName());
System.out.println(product.getDescription());
}
JUnit Test for findByPriceGreaterThan Query Method:
@Test
void findByPriceGreaterThanMethod(){
List<Product> products = productRepository.findByPriceGreaterThan(new BigDecimal(100));
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
JUnit Test for findByPriceLessThan Query Method:
@Test
void findByPriceLessThanMethod(){
List<Product> products = productRepository.findByPriceLessThan(new BigDecimal(200));
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
JUnit Test for findByNameContaining Query Method:
@Test
void findByNameContainingMethod(){
List<Product> products = productRepository.findByNameContaining("product 1");
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
JUnit Test for findByNameLike Query Method:
@Test
void findByNameLikeMethod(){
List<Product> products = productRepository.findByNameLike("product 1");
products.forEach((p) -> {
System.out.println(p.getId());
System.out.println(p.getName());
});
}
JUnit Test for findByPriceBetween Query Method:
@Test
void findByPriceBetweenMethod(){
List<Product> products = productRepository.findByPriceBetween(
new BigDecimal(100), new BigDecimal(300)
);
products.forEach((p) ->{
System.out.println(p.getId());
System.out.println(p.getName());
});
}
JUnit Test for findByDateCreatedBetween Query Method:
@Test
void findByDateCreatedBetweenMethod(){
// start date
LocalDateTime startDate = LocalDateTime.of(2022,02,13,17,48,33);
// end date
LocalDateTime endDate = LocalDateTime.of(2022,02,13,18,15,21);
List<Product> products = productRepository.findByDateCreatedBetween(startDate, endDate);
products.forEach((p) ->{
System.out.println(p.getId());
System.out.println(p.getName());
});
}
7. Conclusion
In this article, we have seen how to create Spring Data JPA query methods by using the query generation from the method name strategy.8. Related Spring Data JPA Tutorials and Examples
- Spring Data JPA Tutorial - Getting Started // Popular
- How to use Spring Data JPA in Spring Boot Project // Popular
- Spring Data JPA Tutorial - Java-Based Configuration
- Spring Data JPA - Query Creation from Method Names // Popular
- Spring Data JPA - Creating Database Queries With Named Queries
- Spring Data JPA @NamedNativeQuery and @NamedNativeQueries Example
- Spring Data JPA - @NamedQuery Example
- Spring Data JPA - @NamedQueries Example
- Spring Data JPA - Creating Database Queries using @Query Annotation
- Spring Data JPA - Auditing with Spring Boot 2 and MySQL Example // Popular
- Spring Data JPA - Working with Multiple Datasources using Spring Boot
- Spring @Repository Annotation
- Spring MVC 5 + Spring Data JPA + Hibernate 5 + JSP + MySQL Tutorial
- Spring Data REST Tutorial
- Spring Boot CRUD Tutorial with Spring MVC, Spring Data JPA, Thymeleaf, Hibernate, MySQL
- Spring Data JPA CRUD Example Tutorial // Popular
How to write this query by method
ReplyDelete@Query(value = "SELECT user FROM User server WHERE user.firstName LIKE :s% or user.lastName LIKE :s% ")
This one actually
Delete@Query(value = "SELECT user FROM User user WHERE user.firstName LIKE :s% or user.lastName LIKE :s% ")
REPLY
u r the best...keepgoing...gbu....
ReplyDelete