0
votes

Using hibernate I have the following query

    String PQ = "select k from Customer k inner join k.winterSet vs where vs.year = :year";
    TypedQuery<Customer> tq = legacyEm.createQuery(PQ,Customer.class);
    tq.setParameter("year", DateUtil.getCurrentWinterSeason());
    List<Customer> result = tq.getResultList();

The mapping in Customer is

@OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
private Set<Winter> winterSet = new HashSet<>(0);

and in Winter

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "cnr")
private Customer customer;

When I run this query I get only rows from Customer that actually has a related row in Winter with the attribute year matching the given parameter. So far so good. However those Customer objects have their winterSet populated with all the related Winter objects, not only those with the desired value in the year attribute. How can I achieve that?

2

2 Answers

0
votes

That is perfectly normal and expected results. With mappings you define structure of entities, including relations to other entities. Query defines which ones of these entities are in result.

With FetchType you can partially control is some persistent attribute of queried entity fetched or not. But there is no mechanism to populate only some elements of collection.

If you need result that presents only some part of the data in entity, then you can create new class presenting partial result and populate it with query and constructor expression.

0
votes

Join fetch does the trick:

String PQ = "select k from Customer k inner join FETCH k.winterSet vs where vs.year = :year";

Debugging hibernate indicates that the sql produced includes the where-clause. But, because the relation is mapped LAZY, the collection isn't populated from this query, only the Customer objects are. When the collection is accessed later on, loading is triggered, but at this point, the were-clause is long gone, and all objects are loaded.

However, when using "join fetch", which actually loads all objects from the query at once, hibernate populates everything from the resultset of the query, and hence only the desired objects are present in the collection. This is ofcourse much more efficient, there is only one query executed, and no need for loading each of the objects in the collection afterwards, just to throw most of them away.

Edit: only works in hibernate, and may have severe side effects if result is modified. See comment.