0

所以我有2层休眠的POJO如下标准查询

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 *会非常昂贵,因为所有者表具有超过60列,并且具有与其他许多表的外键关系。我想要使​​用投影来仅选择所需的列,以便查询执行得更快。如果我添加预测和/或别名,我得到的业主,但没有猫(每个所有者的猫为空)。

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

其他人面临类似的问题?有任何想法吗?

回答

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; 

我想是你想获得再怎么做,在休眠首先应该做的事情很重要。

编辑: 好吧,我想我明白你现在想完成什么。但我不认为你能够像你想要的那样去做 - 直接提取也填充了猫的Owner实体。这是因为默认情况下,通过应用投影,结果不会是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相似。

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

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

现在第一个将被要求在结果列表中的每个对象,如果你想返回的每一行映射到一个对象,但如果你愿意,你可以处理整个列出并合并结果。也许你会这样做,因为例如,您将拥有一个拥有猫颜色列表或catDtos列表的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中的投影数据进行转换并使用它们更有意义,因为这就是为什么您首先使用投影 - 不检索整个实体,对吗?

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

+0

感谢您的回复。 我更新了问题,以便更清楚。我需要各自的猫主人名单。我正在使用预测,以避免40多列与许多人再次有其他表的外键关系。预测将有助于大幅缩短查询执行时间。 –

+0

编辑答案包括一个可能的解决方案,让我知道你在想什么。 –