Граф сущности jpa с запросом по дочернему атрибуту

Я использую EntityGraphs jpa 2.1 для изменения различных запросов jpa, и в некоторых случаях EntityGraphs не работают должным образом. Простой вариант использования, с которым я борюсь, - это

Author в качестве родительского класса с однонаправленным отношением один ко многим к дочернему классу Book, и я хочу получить результаты авторов для данного имени книги, например findAllAuthorsByBookName.

мой класс Author выглядит так

@Entity
@NamedEntityGraph(name = "graph.author.detail", attributeNodes = {
        @NamedAttributeNode("books")
})
public class Author extends GenericEntity {

    @OneToMany
    @JoinColumn(name="author_id")
    private Set<Book> books = new HashSet<Book>();
....

В книге нет ссылки на автора, поэтому она выглядит так

@Entity
public class Book extends GenericEntity {
...

Общий класс Entity просто имеет атрибуты id и name.

Вот как я запрашиваю данные.

EntityGraph graph = em.getEntityGraph("graph.author.detail");       
Author author = (Author) em.createQuery("select a from Author a left join a.books b where b.name = 'book 1'")
                            .setHint("javax.persistence.loadgraph", graph).getResultList().get(0);

Это не работает. Я ожидаю, что класс Author будет возвращен с загруженными атрибутами книг, потому что он указан в графе сущностей, но в этом случае атрибут книг загружен лениво и выдает исключение LazyInitialziation. Если вместо этого я использую атрибут автора для предложения where (например, select a from Author a where a.id = 1), то он работает нормально и с готовностью загружает атрибут books.

Любые идеи были бы хорошы.


person adeelmahmood    schedule 04.11.2014    source источник


Ответы (1)


Я испытываю нечто подобное с JPA 2.1/Hibernate. Я полагаю, что, поскольку вам уже нужно присоединиться к коллекции книг в вашем запросе, Hibernate игнорирует подсказку EntityGraph. Лучшее, что вы можете сделать, это 'left join fetch' в вашем запросе. Не просто 'left join'.

Следует отметить, что мне кажется, что запрос, который вы действительно хотите, таков:

"select a from Author a where exists (select 1 from Book b where b.authorId = a.id and b.name = 'book 1')"

Это вернет всех авторов, у которых есть книга с именем 'book 1'. Возможно, теперь EntityGraph hint будет работать корректно, и в результатах не будет дублирования авторов.

Кроме того, приведенный выше запрос предполагает, что вы, по крайней мере, сопоставите столбец author_id с полем в объектах Author и Book, если не просто установите двунаправленную связь (в этом случае она replace b.authorId = a.authorId with b.author = a.)

person Paul    schedule 09.02.2015