Spring Boot Data JPA sort

last modified July 25, 2023

In this article we show how to sort query results in Spring Data JPA. Query results are sorted either with ORDER BY clause or with a Sort object.

Spring is a popular Java application framework and Spring Boot is an evolution of Spring that helps create stand-alone, production-grade Spring based applications easily.

Spring Data JPA

Spring Data JPA is part of the umbrella Spring Data project that makes it easier to implement JPA based repositories. Spring Data JPA uses JPA to store data in a relational database. It can create repository implementations automatically, at runtime, from a repository interface.

Spring Data JPA sorting

In Spring Data JPA query results can be sorted in two ways:

Spring Boot Data JPA sort example

The following application retrieves cities sorted in ascending order.

│   ├───java
│   │   └───com
│   │       └───zetcode
│   │           │   Application.java
│   │           ├───controller
│   │           │       MyController.java
│   │           ├───model
│   │           │       City.java
│   │           ├───repository
│   │           │       CityRepository.java
│   │           └───service
│   │                   CityService.java
│   │                   ICityService.java
│   └───resources
│           application.properties
│           data-h2.sql
│           schema-h2.sql

This is the project structure.

plugins {
    id 'org.springframework.boot' version '3.1.1'
    id 'io.spring.dependency-management' version '1.1.0'
    id 'java'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    runtimeOnly 'com.h2database:h2'

This is the Gradle build file.


In the main properties file, we turn off the Spring Boot banner with the spring.main.banner-mode property. The spring.sql.init.platform is set to h2, so the database name is present in the database initialization scripts. Since we initialize scripts from SQL code, we turn off automatic creation of tables from entities by settting spring.jpa.hibernate.ddl-auto to none.

package com.zetcode.model;

import java.util.Objects;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Table(name = "cities")
public class City {

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

    private String name;
    private int population;

    public City() {

    public City(String name, int population) {
        this.name = name;
        this.population = population;

    public Long getId() {
        return id;

    public void setId(Long id) {
        this.id = id;

    public String getName() {
        return name;

    public void setName(String name) {
        this.name = name;

    public int getPopulation() {
        return population;

    public void setPopulation(int population) {
        this.population = population;

    public int hashCode() {
        int hash = 7;
        hash = 79 * hash + Objects.hashCode(this.id);
        hash = 79 * hash + Objects.hashCode(this.name);
        hash = 79 * hash + this.population;
        return hash;

    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        if (obj == null) {
            return false;
        if (getClass() != obj.getClass()) {
            return false;
        final City other = (City) obj;
        if (this.population != other.population) {
            return false;
        if (!Objects.equals(this.name, other.name)) {
            return false;
        return Objects.equals(this.id, other.id);

    public String toString() {

        var builder = new StringBuilder();
        builder.append("City{id=").append(id).append(", name=")
                .append(name).append(", population=")

        return builder.toString();

This is the City entity.

    name VARCHAR(255), population INT);

When the application is started, the schema-h2.sql script is executed. It creates a new database table.

INSERT INTO cities(name, population) VALUES('Bratislava', 432000);
INSERT INTO cities(name, population) VALUES('Budapest', 1759000);
INSERT INTO cities(name, population) VALUES('Prague', 1280000);
INSERT INTO cities(name, population) VALUES('Warsaw', 1748000);
INSERT INTO cities(name, population) VALUES('Los Angeles', 3971000);
INSERT INTO cities(name, population) VALUES('New York', 8550000);
INSERT INTO cities(name, population) VALUES('Edinburgh', 464000);
INSERT INTO cities(name, population) VALUES('Suzhou', 4327066);
INSERT INTO cities(name, population) VALUES('Zhengzhou', 4122087);
INSERT INTO cities(name, population) VALUES('Berlin', 3671000);

Later, the data-h2.sql file is executed. It fills the table with data.

package com.zetcode.service;

import com.zetcode.model.City;

import java.util.List;

public interface ICityService {

    List<City> findAllOrderByPopulationAsc();
    List<City> findAllOrderByNameAsc();

ICityService contains two contract methods.

package com.zetcode.service;

import com.zetcode.model.City;
import com.zetcode.repository.CityRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;

public class CityService implements ICityService {

    private final CityRepository repository;

    public CityService(CityRepository repository) {
        this.repository = repository;

    public List<City> findAllOrderByPopulationAsc() {
        return repository.findAllOrderByPopulationAsc();

    public List<City> findAllOrderByNameAsc() {

        var sort = Sort.by(Sort.Direction.ASC, "name");
        return repository.findAllOrderByNameAsc(sort);

Here we have the implementations of the two sorting methods.

public List<City> findAllOrderByNameAsc() {

    var sort = Sort.by(Sort.Direction.ASC, "name");
    return repository.findAllOrderByNameAsc(sort);

The Sort.by sorts the query results by name in ascending order. It is passed to the findAllOrderByNameAsc method as a parameter.

package com.zetcode.repository;

import com.zetcode.model.City;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

public interface CityRepository extends CrudRepository<City, Long> {

    @Query("FROM City ORDER BY population ASC")
    List<City> findAllOrderByPopulationAsc();

    @Query("FROM City")
    List<City> findAllOrderByNameAsc(Sort sort);

CityRepository has two sorting methods. In the first case, we use the ORDER BY clause. In the second case, we use the Sort object.

package com.zetcode.controller;

import com.zetcode.model.City;
import com.zetcode.service.ICityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

public class MyController {

    private final ICityService cityService;

    public MyController(ICityService cityService) {
        this.cityService = cityService;

    @GetMapping(value = "/cities")
    public List<City> getCitiesByPopulation() {

        return cityService.findAllOrderByPopulationAsc();

    @GetMapping(value = "/cities2")
    public List<City> getCitiesByName() {

        return cityService.findAllOrderByNameAsc();

The controller is RESTFul and returns data in a JSON format.

package com.zetcode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

public class Application  {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);

Application is the entry point which sets up the Spring Boot application.

We run the application with ./gradlew bootRun.

$ curl localhost:8080/cities

In this output, the cities are sorted by population in asceding order.

$ curl localhost:8080/cities2

In this output, the cities are sorted by name in asceding order.

This article showed how to sort query results in Spring Boot Data JPA.


My name is Jan Bodnar and I am a passionate programmer with many years of programming experience. I have been writing programming articles since 2007. So far, I have written over 1400 articles and 8 e-books. I have over eight years of experience in teaching programming.

List all Spring Boot tutorials.