OrderBy или OrderColumn


Между JPA аннотациями OrderBy и OrderColumn существует огромная разница.

@OrderBy – аналог обычной SQL команды ORDER BY. Здесь все понятно. Например у вас отношение один ко многим. Для примера возьмем сущность “Новость” и к ней привязано много “Комментариев“. На уровне объектной модели, это значит, что у вас есть объект класса News, у которого есть метод который возвращает список комментариев:

+-----------------------------+
|News                         |
|-----------------------------|
|-----------------------------|
|+getComments(): List<Comment>|
+-----------------------------+

+-----------------+
|Comment          |
|-----------------|
|-----------------|
|+getNews(): News |
+-----------------+

В таком случае, мы должны указать в классе News:

// аннотации
public class News {
// много кода
@OneToMany(targetEntity = Comment.class, mappedBy="news")
@OrderBy(value="pubdate desc")
private List comments;
// много кода
}

Причем сортировка должна быть сделана на уровне БД, через ORDER BY выражение. В данном примере мы сортируем комментарии, по дате их публикации (поле pubdate).

@OrderColumn – задает другой способ оказания порядка (материализованный). В этом случае порядковый номер записи указывается явно в таблице. В Hibernate была аналогичная аннотация @IndexColumn , ее использовали до выхода JPA 2.0. Сейчас по возможности лучше вместо @IndexColumn использовать @OrderColumn. В Hibernate поддерживаются обе.

Разберем пример. Допустим у вас также отношения один ко многим, но в этом случае возьмем сущность Дом в котором живут несколько Постояльцев. Допустим в этом доме в 1-ом номере остановились Ивановы, во 2-ом Петровы, с 3 и 4 – пустуют, в 5 – Кузнецовы.

0 - null
1 - Ивановы
2 - Петровы
3 - null
4 - null
5 - Кузнецовы

Для того, чтобы сохранить информацию кто в каком номере живет, мы явно указываем в табличке с жильцами номер комнаты (поле room).

+-------------------------------+
|House                          |
|-------------------------------|
|-------------------------------|
|+getResidents(): List<Resident>|
+-------------------------------+
+----------------------+
|Resident              |
|----------------------|
| room:Integer         |
+----------------------+

В таком случае, мы пишем в классе House:

// аннотации
public class House {
// много кода
    @OneToMany(targetEntity = Resident.class,  mappedBy="house")
    @OrderColumn(name="room")
    private List residents;
// много кода
}

Внимание! Теперь самое важное. Если в данном случае использовать OrderColumn, то у нас будет список в котором будут дыры! С другой стороны, мы можем сразу по порядковому номеру в списке определить номер комнаты.

// жители:
List list = house.getResidents();
// 2 - Петровы
Resident petrovy = list.get(2) ; 

Отличие от OrderBy фундаментальное!

Если вы неправильно спроектируете зависимости и укажите в первом примере (новости – комментарии) вместо OrderBy аннотациюOrderColumn по дате публикации, то у вас может возникнуть явная ошибка (зависит от БД, ORM и т.д.), а может произойти неявная конвертации поля даты в число.
Например в MySQL + Hibernate это может сработать так. Дата публикации 01.01.2011 – преобразуется в число 2011, в итоге получаем список из null-ов, а в конце после 2011-ной записи – комментарии.

Любое использование либо копирование материалов или подборки материалов сайта, элементов дизайна и оформления допускается лишь с разрешения правообладателя и только со ссылкой на источник: programador.ru

Телеграм канал: @prgrmdr
Почта для связи: vit [at] programmisty.com