Карта последнего ребенка коллекции с JPA и Hibernate (NotNull) - PullRequest
0 голосов
/ 01 февраля 2020

Мне нужно получить последний элемент сущности из коллекции. Я использую @JoinFormula:

@Entity
public class Book {

    @ManyToOne
    @JoinFormula("(select * from
                     (SELECT r.id FROM review r WHERE r.book_id = id ORDER BY r.postedAt DESC)
                   where rownum = 1)")
    private Review 
    ...
}

И это работает fantasti c, но только если в Книге есть какой-то отзыв. В противном случае книга не найдена. Поскольку hibernate преобразует это в перекрестное соединение и использует условие в WHERE операторе:

review_entity.id = 
 (select * from (SELECT r.id FROM review r WHERE r.book_id = id ORDER BY r.postedAt DESC) where rownum = 1)

Есть ли здесь какой-либо вариант для преобразования JoinFormula в левое соединение или что-то вроде этого?

select
        book0_.id as id1_0_0_,
        book0_.title as title2_0_0_,
        book0_.version as version3_0_0_,
        (SELECT
            r.id 
        FROM
            review r 
        where
            r.book_id = book0_.id 
        ORDER BY
            r.postedAt DESC LIMIT 1) as formula1_0_,
        review1_.id as id1_1_1_,
        review1_.book_id as book_id4_1_1_,
        review1_.comment as comment2_1_1_,
        review1_.postedAt as postedAt3_1_1_ 
    from
        Book book0_ 
    left outer join
        Review review1_ 
            on (
                SELECT
                    r.id 
            FROM
                review r 
            where
                r.book_id = book0_.id 
            ORDER BY
                r.postedAt DESC LIMIT 1
        )=review1_.id 
    where
        book0_.id=? 

1 Ответ

0 голосов
/ 01 февраля 2020

Я не уверен, что вы идете, это хорошая идея. Ваша модель предметной области не соответствует действительности, что книга имеет много рецензий. Я понимаю, что вы хотите получить доступ только к последнему обзору, но это, вероятно, лучше сделать отдельным запросом. В противном случае вы можете обновить модель своего домена, чтобы она отражала реальность, но при этом по-прежнему извлекать последний обзор в удобной манере с помощью экстра-ленивого свойства Hibernate.

«Чрезвычайно ленивое» извлечение коллекции - при необходимости доступ к отдельным элементам коллекции осуществляется из базы данных. Hibernate пытается не извлекать всю коллекцию в память, за исключением случаев, когда это абсолютно необходимо (подходит для очень больших коллекций).

@Entity
public class Book {

    @OneToMany
    @LazyCollection(LazyCollectionOption.EXTRA)
    @OrderBy("...")
    private List<Review> reviews; //needn't be exposed via public API

    public Review getLatestReview(){
      return reviews.get(reviews.size() - 1); //or first if ordered desc
    }
}

Предложение Hibernate @Where также можно использовать в качестве альтернативы, чтобы ограничить сбор только одним элемент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...