Java Spring: Enum ключи в (LinkedHa sh) карта не упорядочены - PullRequest
1 голос
/ 08 апреля 2020

Моя сущность Mealplan имеет свойство mealsPerWeek как LinkedHashMap.

@Entity
public class Mealplan {

@Id
private int id;

@ManyToMany
private Map<Weekday, Meal> mealsPerWeek = new LinkedHashMap<>();

public Map<Weekday, Meal> getMealsPerWeek() {
    return mealsPerWeek;
}

}

Ключ свойства карты - Weekday и является перечислением:

public enum Wochentag {
    Monday, Tuesday, Wednesday, Thursday, Friday
}

Теперь я ожидаю, что в моем API Еда отображается в правильном порядке перечисления. Но он отображается довольно случайно:

{
id: 1,
mealsPerWeek: {
  Tuesday: {
   id: 3,
   name: "Salad",
   preis: 3,
   art: "vegan"
},
  Monday: {
   id: 4,
   name: "Linsensuppe",
   preis: 23.5,
   art: "vegan"
},

Как мне упорядочить его в моем REST API, чтобы он отображал ключи в правильном порядке?

Редактировать: я вставляю объекты через data.sql при каждом запуске приложения и понял, что каждый раз порядок отличается rnet.

Исходный код: https://gitlab.com/joshua.olberg/java-spring-backend

Ответы [ 2 ]

3 голосов
/ 08 апреля 2020

Проблема в том, что при загрузке карты (и, как правило, всех коллекций) из БД hibernate использует свои собственные типы коллекций.

https://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/domain/collections.html

Hibernate использует собственные реализации коллекций, которые обогащены семантикой отложенной загрузки, кэширования или обнаружения изменений состояния. По этой причине постоянные коллекции должны быть объявлены как тип интерфейса. Фактический интерфейс может быть java .util.Collection, java .util.List, java .util.Set, java .util.Map, java .util.SortedSet, java .util .SortedMap или даже другие типы объектов (то есть вам нужно написать реализацию org.hibernate.usertype.UserCollectionType).

Как показывает следующий пример, важно использовать тип интерфейса, а не реализацию коллекции , как объявлено в сопоставлении сущностей.

Пример 1. Hibernate использует свои собственные реализации коллекции

@Entity(name = "Person")
public static class Person {
    @Id
    private Long id;

  @ElementCollection
    private List<String> phones = new ArrayList<>();

  public List<String> getPhones() {
        return phones;
    }
}

Person person = entityManager.find( Person.class, 1L );
//Throws java.lang.ClassCastException: org.hibernate.collection.internal.PersistentBag cannot be cast to java.util.ArrayList
ArrayList<String> phones = (ArrayList<String>) person.getPhones();

Поэтому:

private Map<Weekday, Meal> mealsPerWeek = new LinkedHashMap<>();

будет заменен на PersistentMap. Вот почему инициализация карты с помощью EnumMap или TreeMap не удалась.

Вы хотите, чтобы Hibernate использовал PersistentSortedMap, и для этого

  • используйте правильный интерфейс SortedMap
  • добавить @SortNatural или @SortComparator
0 голосов
/ 08 апреля 2020

EnumMap может помочь вам здесь. Порядок итерации основан на заявленном порядке в Enum - https://docs.oracle.com/javase/7/docs/api/java/util/EnumMap.html

...