[Spring](EN) Methods for retrieving the first entity in Spring Data JPA
Environment and Prerequisite
- Java
Method
There are various methods and here I introduce two methods with examples. The post was written after searching inability of using LIMIT 1
in JPQL.
- Using JPA Query Methods
- Using Pageable
Usage and Example
build.gradle
- Below build.gradle can be different per project setting.
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.5'
id 'io.spring.dependency-management' version '1.1.3'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '21'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
compileOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.junit.jupiter:junit-jupiter-api'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
}
tasks.named('bootBuildImage') {
builder = 'paketobuildpacks/builder-jammy-base:latest'
}
tasks.named('test') {
useJUnitPlatform()
}
UserEntity
- Example Entity
package com.example.practice.entity;
import jakarta.persistence.*;
import lombok.*;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = "email")})
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String username;
@Column(nullable = false)
private String gender;
@Column(nullable = false)
private String type;
@Column(nullable = false)
private String email;
@Column(nullable = false)
private String password;
}
UserRepository
Using JPA Query Methods
- Create method name according to naming rule.
- Naming rule can be easily found in official document or below example.
Using Pageable
- An example uses
@Query
and returns aList
and Pageable is passed to method at the end. - The usage can be seen in the test below.
- An example uses
package com.example.practice.repository;
import com.example.practice.entity.UserEntity;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserRepository extends JpaRepository<UserEntity, String> {
// 1. Using JPA Query Methods
UserEntity findFirstByGenderAndTypeOrderByIdDesc(String gender, String type);
// 2. Using Pageable
@Query("SELECT u FROM UserEntity u WHERE u.gender = :gender AND u.type = :type ORDER BY u.id DESC")
List<UserEntity> findFirstByGenderAndTypeOrderByIdDescUsingPageable(@Param("gender") String gender, @Param("type") String type, Pageable pageable);
}
UserRepositoryTest
Using JPA Query Methods
- Call the method as shown in below.
Using Pageable
- Pass ```PageRequest.of(0, 1)``.
PageRequest.of(0, 1)
: Configuring to retrieve one result on the first page
package com.example.practice.repository;
import com.example.practice.entity.UserEntity;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.Arrays;
import java.util.List;
@ExtendWith(SpringExtension.class)
@DataJpaTest
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
public void findFirstByGenderAndTypeOrderByNameDescTest() {
List<UserEntity> userEntities = Arrays.asList(
UserEntity.builder().
email("test1@test.com")
.username("testUsername1")
.password("testPassword1")
.gender("male")
.type("A")
.build(),
UserEntity.builder()
.email("test2@test.com")
.username("testUsername2")
.password("testPassword2")
.gender("female")
.type("A")
.build(),
UserEntity.builder()
.email("test3@test.com")
.username("testUsername3")
.password("testPassword3")
.gender("male")
.type("A")
.build(),
UserEntity.builder()
.email("test4@test.com")
.username("testUsername4")
.password("testPassword4")
.gender("male")
.type("B")
.build(),
UserEntity.builder()
.email("test5@test.com")
.username("testUsername5")
.password("testPassword5")
.gender("female")
.type("A")
.build()
);
userRepository.saveAll(userEntities);
// 1. Using JPA Query Methods
UserEntity resultUser = userRepository.findFirstByGenderAndTypeOrderByIdDesc("male", "A");
Assertions.assertEquals("test3@test.com", resultUser.getEmail());
// 2. Using Pageable
List<UserEntity> resultUsers = userRepository.findFirstByGenderAndTypeOrderByIdDescUsingPageable("male", "A", PageRequest.of(0, 1));
Assertions.assertEquals("test3@test.com", resultUsers.getFirst().getEmail());
}
}