Another question that came up while adventuring through JPA criteria queries. Consider the following entities (pseudocode to make it more concise):
Code:
@Entity
class A
{
@Id
String id;
@ElementCollection
@CollectionTable(name="a_b", joinColumns=@JoinColumn(name="a_id"))
@OrderColumn(name = "i")
List<B> bs;
}
@Embeddable
class B
{
// A bunch of basic fields.
}
Now, suppose we want to query for some As. For each so selected A also fetch the first B in the associated ordered collection of Bs. In other words, the number of Bs that we are fetching per an A is known a priori (as opposed to an undeterminable number of Bs; e.g., fetch all Bs associated to some A).
Code:
int first = ..., max = ...;
CriteriaQuery<A> q = builder.createQuery(A.class);
Root<A> r = q.from(A.class)
@SuppressWarnings("unchecked")
ListJoin<A, B> abJ = (ListJoin<A, B>) r.fetch(A_.bs);
predicates.add(builder.equal(abJ.index(), 0));
TypedQuery<A> tq = em.createQuery(q
.select(r)
.where(predicates.toArray(new Predicate[predicates.size()]))
);
setRange(tq, first, max);
List<A> vs = tq.getResultList();
The fetch join together with the range specification results in the infamous warning 'HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!'. However, because of the additional index predicate, I think Hibernate should be able to optimize query execution not to involve the in memory processing. More generally, for any kind of query where the number of associated entities that are to be fetched is fixed and known a priori, it should be possible to formulate a query that delegates all work to the database system such that in memory processing is optimized away. Do you agree, or am I missing something here? If it is possible, how about filing a feature request issue?