У меня следующая ситуация:
Foo.java
@Entity
public class Foo {
@Id
private long id;
@ManyToOne
@JoinColumn(name = "barId", insertable = false, updatable = false)
private Bar bar;
}
Bar.java
@Entity
public class Bar {
@Id
private long id;
@OneToMany(mappedBy = "compositeId.barId")
private HashSet<Xpto> xptos;
}
Xpto.java
@Entity
public class Xpto {
@EmbeddedId
private XptoId compositeId
@MapsId("axisRailroadId")
@ManyToOne
@JoinColumn(name = "barId")
private Bar bar;
}
@Embeddable
class XptoId {
@Column(name = "barId")
private long barId;
@Column(name = "stringKey")
private String someStringKey;
}
И у меня есть запрос, в котором я выбираю Foo
s и использую свойства Xpto
. Если мне нравится:
QFoo qFoo = QFoo.foo;
List<Foo> foos = query.from(foo).fetch();
// Use the foos list
Это работает, но я вижу в своем журнале, что Hibernate обращается к базе данных каждый раз, когда мне нужно Bar
или Xpto
от объекта Foo
.
Пытаясь сделать все это в одном запросе с Joins, я попытался:
- Установка типов выборки на
EAGER
- Это не сработало, тот же результат (я знаю, что это плохо в любом случае)
- Использование Hibernate
@Fetch(FetchMode.JOIN)
- Это не работает, ничего не меняет ... Может быть, потому что QueryDSL или Spring-Data влияют на на это ...?
Одна вещь, которую я думаю, сработает, это создание соединений вручную с помощью QueryDSL. Но я застрял на этом. Я пытаюсь:
QFoo qFoo = QFoo.foo;
List<Foo> foos = query.from(qFoo)
.leftJoin(foo.bar).fetchJoin()
.leftJoin(foo.bar.xptos).fetchJoin()
.fetch();
Выдает исключение, например:
org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
[FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=Xpto,role=com.example.Bar.xptos,tableName=xpto,tableAlias=...
select foo ↵from com.example.Foo foo left join fetch foo.bar left join fetch foo.bar.xptos as xptos]
Я тоже пробовал как:
QFoo qFoo = QFoo.foo;
QXpto qXpto = QXpto.xpto;
List<Foo> foos = query.from(qFoo)
.leftJoin(foo.bar).fetchJoin()
.leftJoin(qXpto).on(qFoo.barId.eq(qXpto.compositeId.barId)).fetchJoin()
.fetch();
Это хорошо работает, и я вижу следующий запрос:
Hibernate:
/* select
foo
from
Foo foo
left join
fetch foo.bar
left join
fetch Xpto xpto with foo.barId = xpto.compositeId.barId
Но дело в том, что когда я получаю доступ к списку Foos
, я все равно вижу, что Hibernate запрашивает XPTOs
. Как будто он не узнал, что он уже был извлечен из базы данных.
Есть идеи, как заставить это работать?