简体   繁体   中英

Hibernate: fetching only the list of associated entities

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM