Подтвердить что ты не робот

JPA/спящий сортированный сборник @OrderBy vs @Sort

Я хотел бы иметь набор дочерних объектов (здесь пример кошки-котенка), которые упорядочены. И сохраните свой порядок при добавлении новых элементов.

@Entity 
public class Cat {
  @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
  @OrderBy("name ASC")
  private List<Kitten> kittens;

  public void setKittens(List<Kitten> kittens) { this.kittens = kittens; }
  public List<Kitten> getKittens() { return kittens; } 
}

Когда я сделаю cat.getKittens.add(newKitten), порядок по имени будет нарушен.

Возможно ли, чтобы спящий режим выполнял работу по упорядочению коллекции? Используя аннотацию @Sort hibernate? @Sort имеет тот недостаток, что он заставляет вас реализовать интерфейс Comparable... Каким будет правильный "чистый JPA" способ сделать это? Сохранение всего в БД и его перезагрузка? Имеет смысл объединить @OrderBy и @Sort?

Обновление Решение до сих пор заключается в объединении @OrderBy и @Sort. @OrderBy приводит к предложению ORDER BY в сгенерированном SQL, который лучше подходит для производительности (я предполагаю, что java снова "сортируется" при вставке в отсортированный контейнер, но это должно быть намного быстрее, потому что элементы уже отсортированы) @Sort вместе с реализованным интерфейсом Comparable приводит к всегда отсортированному контейнеру. Обратите внимание, что теперь я использую SortedSet вместо List. Здесь обновленный Код:

@Entity 
public class Cat {
  @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
  @OrderBy("name ASC")
  @Sort(type = SortType.NATURAL)
  private SortedSet<Kitten> kittens;

  public void setKittens(SortedSet<Kitten> kittens) { this.kittens = kittens; }
  public SortedSet<Kitten> getKittens() { return kittens; } 
}
4b9b3361

Ответ 1

Если вы хотите избежать нестандартных аннотаций, вы можете сделать kittens использование некоторой сортированной реализации Collection. Это гарантирует, что kittens всегда находится в упорядоченном порядке. Что-то вроде этого:

@Entity 
public class Cat {
  @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
  @OrderBy("name ASC")
  private SortedSet<Kitten> kittens = new TreeSet<>();
}

Обратите внимание, что для этого подхода также требуется Kitten реализовать Comparable (альтернативно, вы можете передать Comparator в свой конструктор TreeSet). Кроме того, я использую Set, потому что я не знаю никакой стандартной сортированной реализации List, и я предполагаю, что Cat не имеет клонов в своем помете = p.

Update: Я не уверен, насколько придирчивый Hibernate с определениями getter/setter, но с EclipseLink мне удалось полностью удалить сеттер и обернуть List, возвращенный моим получателем в вызове Collections.unmodifiableList(...). Затем я определил специальные методы для изменения коллекции. Вы можете сделать то же самое и заставить вызывающих использовать метод добавления, который вставляет элементы в отсортированном порядке. Если Hibernate жалуется, что у вас нет геттера/сеттера, возможно, вы можете изменить модификатор доступа? Я думаю, это сводится к тому, насколько вы готовы пойти, чтобы избежать нестандартных зависимостей.

Ответ 2

В последней версии Hibernate используются новые аннотации для этого:

@SortNatural
@OrderBy("name ASC")
private SortedSet<Kitten> kittens = new TreeSet<>();

Есть две части:

  • Аннотация @OrderBy указывает, что предложение order by должно быть добавлено в запрос базы данных при извлечении связанных записей.
  • Аннотация @SortNatural предполагает, что Kitten реализует интерфейс Comparable и использует эту информацию при построении экземпляра TreeSet. Обратите внимание, что вы можете заменить его на аннотацию @SortComparator, которая позволяет указать класс Comparator, который будет передан конструктору TreeSet.

См. документацию: https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#collections-sorted-set

Ответ 3

@Entity 
public class Cat {
  @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
  private Set<Kitten> kittens = new TreeSet<>();
}

Не нужно писать

@OrderBy("name ASC")

Make Sure Kitten Class реализует совместимый интерфейс.