JPA аннотация @OrderBy не сортирует записи

111
09 августа 2019, 18:00

у меня есть пара сущностей, Master и Padawan, один мастер может иметь несколько падаванов.

Мне требуется чтобы при чтении из базы мастера, в поле padawans была сортировка по поле age:

@Entity
@NoArgsConstructor
@Getter
@Setter
public class Master {
    @Id
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    @GeneratedValue(generator = "uuid")
    private String id;
    private String name;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @OrderBy("age")
    private List<Padawan> padawans = new ArrayList<>();
    public Master(String name) {
        this.name = name;
    }
}

@Entity
@NoArgsConstructor
@Getter
@Setter
public class Padawan {
    @GeneratedValue
    @Id
    private int id;
    private String name;
    public int age;
    public Padawan(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Padawan{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

и сам класс, из которого произвожу запуск:

 public static void main(String[] args) {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myUnit");
        EntityManager entityManager = factory.createEntityManager();
        Master master = new Master("Kwigon Jeen");
        Padawan padawan1 = new Padawan("Obi One", 15);
        Padawan padawan2 = new Padawan("Lee", 19);
        Padawan padawan3 = new Padawan("Ganz", 13);
        Collections.addAll(master.getPadawans(), padawan1, padawan2, padawan3);
        entityManager.getTransaction().begin();
        entityManager.persist(master);
        entityManager.getTransaction().commit();
        factory.getCache().evictAll();
        Master res;
        entityManager.getTransaction().begin();
        res = entityManager.find(Master.class, master.getId());
        entityManager.getTransaction().commit();
        res.getPadawans().stream().forEach(padawan -> System.out.println(padawan));
        entityManager.close();
        factory.close();
    }

Но проблема в том, что список padawans выводится неотсортированным.

Padawan{id=1, name='Obi One', age=15} Padawan{id=2, name='Lee', age=19} Padawan{id=3, name='Ganz', age=13}

p.s.

1) Пробовал совсем убрать Lombok

2) Пробовал изменить цикл вывода со стримов на foreach:

  for (Padawan p : res.getPadawans()){
        System.out.println(p);
    }

3) Менял цикл вывода на foreachOrdered

res.getPadawans().stream().forEachOrdered(padawan -> System.out.println(padawan));
Answer 1

Проблема в том, что вы пытаетесь получить осортированный список, который уже есть в кеше 1-го уровня, очистив при этом кеш 2-го уровня. Hibernate не обращает внимание на порядок сортировки списка в кеше, ему важно лишь его наличие чтобы не формировать запрос к базе (аннотация @OrderBy влияет на порядок только при получении данных). Соответственно для генерации запроса и получения отсортированного списка можно либо очистить кеш 1-го уровня:

entityManager.clear();

либо отсоединить объект от контекста:

entityManager.detach(master); 

либо пересоздать контекст:

entityManager.close();
entityManager = factory.createEntityManager();
READ ALSO
java 9 resources

java 9 resources

Вообщем штука такая Я пытаюсь получить InputStream через getClass()getResourceAsStream("/assets/fxml/auth

128
Как создать один GUI для многих программ?

Как создать один GUI для многих программ?

Я новичок в JavaFXСоздал приложение с тремя элементами: текстовое поле для ввода числа, кнопка "подтвердить" и лабель для отображения результата

138
Локальная переменная в теле цикла

Локальная переменная в теле цикла

На различных специализированных интернет-ресурсах бытует множество мнений по этому вопросуПорой эти мнения диаметрально отличаются друг...

91