JPQL для выбора всех объектов, но с помощью setMaxResult для коллекций объектов

#java #hibernate #orm #jpql

#java #спящий режим #orm #jpql

Вопрос:

У меня есть 3 объекта:

Пользователь, который установил галереи. Галерея, в которой установлены фотографии.

Теперь я хочу выбрать всех пользователей с их последними 3 фотографиями к моменту создания (у пользователя может быть 10 галерей и 100 фотографий для каждой галереи). Как я могу выполнить jpql?

Я не знаю, как получить 3 лучших фотографии (выберите 3 лучших из p) ниже:

Запрос q = em.CreateQuery(«выберите u, (выберите top 3 из p) от пользователя u слева присоединиться к u.галереи g слева присоединиться к g.фотографии p»);

Я знаю, что могу получить только одного пользователя с 3 лучшими фотографиями по:

Запрос q = em.CreateQuery(«выберите u, p у пользователя u слева присоединиться к u.галереи g слева присоединиться к g.фотографии p где u.id =:Идентификатор пользователя»).setMaxResults(3);

Но как насчет всех пользователей в одном jpql?

Заранее спасибо.

Комментарии:

1. Как узнать последние 3 фотографии по времени загрузки или времени создания?

2. какую часть вы не понимаете, объединение, сортировку или ограничение?

3. Пожалуйста, обновите свой вопрос created time , указав, что он будет использоваться для последних 3 фотографий, а также код и результат, которые вы пробовали до сих пор!

Ответ №1:

Вы работаете с PostgreSQL, поэтому вы можете использовать функцию окна для выбора первых 3 photo.ids пользователем:

 List<Long> photoIds = (List<Long>) em.createNativeQuery("""
    select data.p_id
        from 
        (
            SELECT p.id as p_id, row_number() as rw OVER w as rw
            FROM photo p
            INNER JOIN galley g on g.id = p.galery_id
            INNER JOIN user u on u.id = g.user_id
            WINDOW w AS (PARTITION BY u.id ORDER BY p.creation_time DESC)
        ) data 
        where rw <= 3
        """, Long.class)
.getResultList(); 
  

Затем с их photoIds помощью вы можете получить фотографию / галерею / пользователя:

 List<Photo> photos = (List<Photo>) em.createQuery("""
    select p
    from Photo p
    join fetch p.gallery g
    join fetch g.user u
    where p.id in (:photoIds)
    """)
.setParameter("photoIds", photoIds) 
.getResultList();
  

Затем вы можете воссоздать пользователя / галерею / фотографию обратно из списка фотографий.

Нет другого способа использовать JPQL для выбора только частичных представлений над объединенной коллекцией дочерних объектов.

Комментарии:

1. Я вижу ваш подход. Запрос со стороны многих, а не запрос с одной стороны. Хорошая идея. Спасибо.