Reputation: 3162
I'm kind of lost in the woods at this point trying to optimize how Hibernate gets its data from the database. Here's the case:
I have a Person class that has a OneToMany association with the Address class. At the time of querying it is known from the application point of view that we're not going to need the Person instance but we'd like to have the list of that Person's Addresses.
The classes look more/less like this (getters/setters omitted):
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
@Column
private String firstName;
@Column
private String lastName;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name="address_id")
private Set<Address> addresses = new HashSet<Address>();
//...
}
@Entity
public class Address {
@Id
@GeneratedValue
private Long id;
@Column
private String city;
@Column
private String street;
//...
}
Now what I'd like to achieve is a criteria query (I have all the other parts of the system already using Criteria API and I'd very much like to keep it consistent) that'll return addresses belonging to a given person.
Upvotes: 0
Views: 2107
Reputation: 692121
Criteria is the limiting factor here: it only allows to select the root entity, or scalars. And since you don't have the reverse association (from address to person), it's not possible to do it in a simple way with Criteria.
I find HQL much more flexible, and much more readable as well. Criteria is useful when a query must be dynamically composed, but in this case, using a HQL query is straightforward:
select a from Person p inner join p.addresses a where p.id = :personId
It's actually doable in Criteria, but it would need a query which is less efficient and straightforward: something like
select a from Address a where a.id in (select a2.id from Person p inner join p.addresses a2 where p.id = :personId)
translated in Criteria.
That would be:
Criteria criteria = session.createCriteria(Address.class, "a");
DetachedCriteria dc = DetachedCriteria.forClass(Person.class, "p");
dc.createAlias("p.addresses", "a2");
dc.add(Restrictions.eq("p.id", personId);
dc.setProjection(Projections.property("a2.id"));
criteria.add(Subqueries.propertyIn("a.id", dc));
As you see: less readable, much longer, and less efficient.
Upvotes: 1