Автоматическая сортировка отображаемых коллекций типа Set и Map методом compareTo() с помощью аннотации @SortNatural

Если отображаемый класс содержит поля типа SortedMap или SortedSet, то их можно пометить аннотацией @SortNatural. И тогда после выборки данных из БД, если они, как большинство базовых типов, имплементируют интерфейс Comparable, то они будут отсортированы методом compareTo() и будут доступны в этих полях уже в отсортированном виде.

Отметим, что при таком подходе сортировка будет проведена в java-приложении. Если нужна сортировка выборки на стороне БД, то это делается аннотациями @javax.persistence.annotations.OrderBy или @org.hibernate.annotations.OrderBy.

Подготовка

Создадим базовое веб-приложения на связке Spring Boot 3 + Hibernate + PostgreSQL

Убедитесь, что файле /src/main/resources/application.properties есть следующая строка, позволяющая Hibernate’у автоматически создавать (и обновлять) схему БД при запуске приложения на основании аннотаций в классах предметной области:

spring.jpa.hibernate.ddl-auto=update

Код

Создадим класс предметной области, содержащий поле типа SortedSet<String>:

Мы помечаем поле SortedSet<String> emails аннотацией @org.hibernate.annotations.SortNatural. Этим мы указываем Hibernate’у сортировать данные этой коллекции при выборке, используя метод compareTo(). Имя аннотации пишем целиком, так как это специфичная Hibernate аннотация, не являющаяся частью JPA.

Создадим репозиторий с кастомным запросом, который будет делать выборку из двух таблиц: PERSON и из связанной с ней таблицы EMAILS:

Напишем тест, который продемонстрирует работу нашего кода:

В данном тесте мы трижды сохраняем объект irina в БД, каждый раз добавляя в поле SortedSet<String> emails новый адрес электронной почты. Причём добавляем адреса в порядке обратном алфавитному: ccc@mail.ru, bbb@mail.ru, aaa@mail.ru.

После выборки данных из БД мы видим, что они оказываются отсортированными в алфавитном порядке. После выборки данных из БД поле SortedSet<String> emails оказывается имплементированным классом PersistentSortedSet<String> и мы имеем сортировку в алфавитном порядке именно потому, что Hibernate использовал стоковый метод compareTo() класса String.

Сравним порядок полученных данных с тем, как они хранятся в БД:

В БД строки лежат в порядке обратном алфавитному, так как мы приложили к этому особые усилия, сделав целых три сохранения объекта irina. Тем не менее при выборке, как мы видели в тесте, эти данные оказываются отсортированы по алфавиту.