Java Hibernate:仅获取关联实体的列表
我在尝试优化Hibernate从数据库获取数据的方式时有点不知所措。情况是这样的: 我有一个Person类,它与Address类有一个OneToMany关联。在查询时,从应用程序的角度来看,我们不需要Person实例,但我们希望得到此人的地址列表 这些类看起来大致如下(省略了getter/setter):Java Hibernate:仅获取关联实体的列表,java,hibernate,Java,Hibernate,我在尝试优化Hibernate从数据库获取数据的方式时有点不知所措。情况是这样的: 我有一个Person类,它与Address类有一个OneToMany关联。在查询时,从应用程序的角度来看,我们不需要Person实例,但我们希望得到此人的地址列表 这些类看起来大致如下(省略了getter/setter): @实体 公共阶层人士{ @身份证 @生成值 私人长id; @纵队 私有字符串名; @纵队 私有字符串lastName; @OneToMany(级联=级联类型.ALL) @JoinColumn(
@实体
公共阶层人士{
@身份证
@生成值
私人长id;
@纵队
私有字符串名;
@纵队
私有字符串lastName;
@OneToMany(级联=级联类型.ALL)
@JoinColumn(name=“address\u id”)
私有集地址=新HashSet();
//...
}
@实体
公共课堂演讲{
@身份证
@生成值
私人长id;
@纵队
私人城市;
@纵队
私家弦街;;
//...
}
现在我想实现的是一个条件查询(我已经使用了系统的所有其他部分的条件API,我非常希望保持一致),它将返回属于给定人员的地址。这里的条件是限制因素:它只允许选择根实体或标量。而且,由于您没有反向关联(从地址到人),因此不可能用标准的简单方式来实现 我发现HQL更灵活,可读性也更高。当查询必须动态组合时,条件非常有用,但在这种情况下,使用HQL查询非常简单:
select a from Person p inner join p.addresses a where p.id = :personId
它实际上在标准中是可行的,但它需要一个效率和简单程度较低的查询:比如
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));
正如您所看到的:可读性差,时间长,效率低。尝试向
地址添加双向关系:@ManyToOne(mappedBy=“addresses”)私人代码>。您可以简单地查询:person
所在的所有地址……是的。。双向映射在这一点上是不可能的。。。这些映射就是这样的,我无法更改它们。所以我只有上面例子中的内容…有趣的是,在SQL中,这将非常简单-您只需将需要的列限制为来自关联的列,而忽略那些针对包含实体的列…这里的情况实际上是,我并不真正了解基础模型,它将发生变化。我正在构建一个通用实用程序,通过REST公开GORM(Grails ORM)映射类。所以标准听起来像是一条路,但我真的很讨厌它看起来的样子。。。事实上,我认为即使手动编写HQL也不会那么痛苦。这真的很简单!谢谢
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));