2012-10-31 55 views
1

这是我试图用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对象列表。

现在我无法理解投影如何使用Hibernate。这是我的目标。我有大型的实体,我必须加载,但我不需要所有的数据,我只需要加载几列和一个子集合,我不需要所有其他数据。基本上我想加载相同的对象只是有限的数据量。但是,我不需要用户对象的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和无用户对象!

如果我试试这个:

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 

这只是失败!

看起来投影只会返回您想要的确切数据而不是实体。我期待用户对象返回部分填充字段。

也许我正在错误地解决这个问题?

回答

0

你做错了,我想。不确定你真正想获得什么,但是听起来像你需要在映射中进行一些惰性/代理加载,而不是预测。

设置加载规则不必要列lazy ="true"的属性或lazy="proxy"的集合。然后,它们将不会从数据库加载,直到您尝试在代码中使用它们。

还要记住检查获取方法(fetch="select"),也许批处理 - 如果你有很多数据在收集,但只需要其中一些显示在一次。

如果你需要的是投影,你应该从地址开始,因为你必须在你的查询的一些连接。我的建议是 - 首先尝试在SQL中编写查询,而不是将其放入Hibernate的Cirteria api中(至少在您了解其工作原理以及如何正确使用它之前)。