这是一个非常简化的例子,说明我想用Hibernate和投影来实现的目标。以下是一些示例表:
class User{
int id;
String firstName;
String lastName;
List<Address> address ;
}
class Address{
int id;
String city;
String state;
User user;
}
这是我如何定期选择数据。
Criteria crit = getSession().createCriteria("User");
crit.add(CriterionUtils.in("id", new Object[]{1,2,3}));
criteria.list();
这适用于并返回完整的User对象和完整的Address列表。这将使用Address对象列表加载完整的User对象。
现在我无法理解Projections如何与Hibernate一起使用。这是我的目标。我有大型实体,我必须加载,但我不需要所有数据,我只需要几个列和一个子集合加载,所有其他数据,我不需要。基本上我想只使用有限数量的数据加载相同的对象。但是,我不想要User对象的firstName和lastName,因为我不需要它们;我想要一个“更轻”的用户对象,其中包含完整的地址列表和用户的ID。请记住,我的目标不是加载地址列表,而是加载具有地址列表的用户对象
如果我试试这个:
ProjectionList proList = Projections.projectionList();
proList.add(Projections.property("id"));
criteria = criteria.setProjection(proList);
criteria.list(); //an Object[] of just the ids
我只获得ID而没有User对象!
如果我试试这个:
ProjectionList proList = Projections.projectionList();
proList.add(Projections.property("id"));
proList.add(Projections.property("address"));
criteria = criteria.setProjection(proList);
criteria.list(); //this actually fails with an Array out of bounds exception
这只是失败了!
Projections似乎只返回您想要的确切数据,而不是实体。我期待用部分填充的字段返回User对象。
也许我这样做不正确?
答案 0 :(得分:0)
我猜错了。不确定你真正想要达到的目标,但听起来你需要在映射中加入一些延迟/代理加载,而不是预测。
将加载规则设置为lazy ="true"
不必要的列,或者lazy="proxy"
收集。然后,在您尝试在代码中使用它们之前,它们不会从DB加载。
还要记住检查fetch方法(fetch="select"
)并进行批处理 - 如果你收集了大量数据,但一次只需要显示少数数据。
如果你需要那个Projection,你应该从Address开始,因为你的查询中有一些连接。我的建议是 - 首先尝试在SQL中编写查询,而不是将其放在Hibernate的Cirteria api中(至少在你了解它是如何工作以及如何正确使用它之前)。