此时我有点迷失在树林中,试图优化Hibernate如何从数据库中获取数据。情况就是这样:
我有一个Person类,它与Address类有一个OneToMany关联。在查询时,从应用程序的角度来看,我们不需要Person实例,但我们希望获得该Person的地址列表。
这些类看起来更像/更少(省略了getters / setters):
@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;
//...
}
现在我想要实现的是标准查询(我已经使用了Criteria API的系统的所有其他部分,我非常希望保持一致),它将返回属于给定的地址人
答案 0 :(得分:1)
标准是限制因素:它只允许选择根实体或标量。而且由于你没有反向关联(从地址到人),因此不可能用Criteria以简单的方式进行。
我发现HQL更灵活,更易读。当查询必须动态组合时,条件很有用,但在这种情况下,使用HQL查询非常简单:
select a from Person p inner join p.addresses a where p.id = :personId
它在Criteria中实际上是可行的,但它需要一个效率低且简单的查询:类似
select a from Address a where a.id in (select a2.id from Person p inner join p.addresses a2 where p.id = :personId)
在标准中翻译。
那将是:
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));
如您所见:可读性更低,时间更长,效率更低。