Spring Boot Data JPA sort tutorial

Spring Boot Data JPA sort tutorial shows 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.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"









This is the Maven pom.xml file.


In the main properties file, we turn off the Spring Boot banner with the spring.main.banner-mode property. The spring.datasource.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 javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.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 CityRepository repository;

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

    public List<City> findAllOrderByNameAsc() {

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

Here we have the implementations of the two sorting methods.

public List<City> findAllOrderByNameAsc() {

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

The Sort object sorts the query results by name in ascending order. The Sort is passed to the 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 ICityService 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 mvn -q spring-boot:run.

$ 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 tutorial showed how to sort query results in Spring Boot Data JPA. You might also be interested in the related tutorials: Spring Boot Data JPA @Query tutorial, Spring Boot Data JPA @NamedQuery tutorial, Java tutorial, or list all Spring Boot tutorials.