0

所以我有2个hibernate pojos如下

class Owner{

Integer id;
String name;
Integer age;
String address;

/* 
  Many more fields here
*/

Set<Cat> cats;

}

class Cat{
Owner owner; //referenced from Owner.id
String color;
}

我正在使用以下条件查询所有者表 -

Criteria criteria = session.createCriteria(Owner.class);
criteria.createAlias("cats", "cats");

ProjectionList projList = Projections.projectionList();
projList.add(Projections.property("id"), "id");
projList.add(Projections.property("name"), "name");
projList.add(Projections.property("cats"), "cats");

criteria.setProjection(projList);
criteria.setResultTransformer(Transformers.aliasToBean(Owner.class));
List<Owner> owners = (List<Owner>)criteria.list();

我需要拥有各自猫的所有者列表。

如果我不添加预测(相当于 select * ),我将为每个所有者填充猫。但是 select * 会非常昂贵,因为所有者表也有 60 多个与许多其他表有外键关系的列。我想使用投影来仅选择所需的列,以便查询执行得更快。如果我添加投影和/或别名,我会得到所有者但没有猫(每个所有者的猫为空)。

我已经为此搜索了很多解决方案,尝试了所有方法来创建标准中的别名和投影,甚至尝试使用自定义 ResultTransformers。当我使用投影时,这些似乎都不起作用。

还有其他人遇到过类似的问题吗?有任何想法吗?

4

1 回答 1

1

问题不是很清楚。您说如果不添加预测,您将为每个所有者填充猫。但是然后在投影列表中添加猫作为投影字段,所以基本上你想要结果中的猫,对吧?如果是这样,使用预测的唯一原因是不包括所有者的年龄和地址?

作为一个建议,请试着想想你从查询中获得的 SQL 是什么?你想要这样的东西:

select id, name from owner;

或者是这样的:

select o.id, o.namer, c.color from owner o join cat c on o.id = c.owner_id; 

我认为首先要获得什么很重要,然后是如何在 Hibernate 中进行操作。

编辑:好的,我想我明白你现在想要完成什么。但我认为您无法按照自己的意愿进行操作 - 直接提取 Owner 实体,其中还填充了猫。这是因为默认情况下,通过应用投影,结果将不是所有者实体列表,而是 Object[] 列表。

例如,假设您想要所有者 ID、所有者名称和猫颜色。您的预测将如下所示:

projList.add(Projections.property("id"), "id");
projList.add(Projections.property("name"), "name");
projList.add(Projections.property("cats.color"), "catsColor");

生成的 sql 将与上面使用 cat join 生成的 sql 类似。

然后您可以应用结果转换器。这是来自接口的方法:

public Object transformTuple(Object[] tuple, String[] aliases);
public List transformList(List collection);

现在将为结果列表中的每个对象调用第一个,如果您想将每一行返回到一个对象,但如果您愿意,您可以处理整个列表并组合结果。也许您会喜欢这样,因为例如您将拥有一个拥有猫颜色列表或 catDto 列表的 OwnerDto,您可以将结果转换为这种树状结构。请注意,由于加入,您的结果将如下所示(假设您有 2 个所有者,每个所有者都有一只猫):

tuple: [1, 'Owner1', 'white'] - aliases ['id', 'name', 'catsColor']
tuple: [1, 'Owner1', 'black'] - aliases ['id', 'name', 'catsColor']
tuple: [2, 'Owner2', 'yellow'] - aliases ['id', 'name', 'catsColor']
.. etc

这就是为什么您想要将这个原始列表组合成更合适的东西的结果转换器。

这个想法是,预测对于仅获取您需要的数据和性能提升非常有用,但是您现在必须返回的结果将不是实体 - 您必须准备它们并像它们一样使用它们。转换 DTO 中的投影数据并像这样使用它们更有意义,因为这就是您首先使用投影的原因——而不是检索整个实体,对吗?

希望这能解决问题,如果您需要更多建议,请发表评论。

于 2016-03-02T08:48:41.917 回答