所以我想在我的项目中使用投影bean来优化加载时间(以避免获得无用的数据......)。
我有这两个内容:父母-----<孩子(与一对多的关联)
在我的数据库中,我有:
我想在一个请求中得到父母和孩子,所以首先我这样做了:
final JPAQueryBase<?> query = createQuery();
final QParent qParent = QParent.parent;
final QChild qChild = QChild.child;
Map<Long, Parent> transform = query.from(qParent)
.leftJoin(qParent.children, qChild)
.transform(GroupBy.groupBy(qParent.id)
.as(Projections.bean(Parent.class,
qParent.id,
qParent.name,
GroupBy.set(qChild).as(qParent.children))));
final List<Parent> parents = new ArrayList<Parent>(transform.values());
它就像一个魅力,结果是这样的:
[
Parent: {
id: 1,
name: "parent1",
children: [
Children: {
id: 1,
name: "child1",
otherAttr: //loaded
},
Children: {
id: 2,
name: "child2",
otherAttr: //loaded
}
],
otherAttr: null
},
Parent: {
id: 2,
name: "parent2",
children: [], //size: 0
otherAttr: null
}
]
但我不想从子实体加载“其他属性”。所以我使用子实体的投影bean进行了这个查询:
final JPAQueryBase<?> query = createQuery();
final QParent qParent = QParent.parent;
final QChild qChild = QChild.child;
Map<Long, Parent> transform = query.from(qParent)
.leftJoin(qParent.children, qChild)
.transform(GroupBy.groupBy(qParent.id)
.as(Projections.bean(Parent.class,
qParent.id,
qParent.name,
GroupBy.set(Projections.bean(Child.class,
qChild.id,
qChild.name))
.as(qParent.children))));
final List<Parent> parents = new ArrayList<Parent>(transform.values());
通过此查询,我可以完全控制要选择的属性。但是当父母没有孩子时,发生了一些奇怪的事情:所有属性都设置为null的Child对象出现在子列表中,如下所示:
[
Parent: {
id: 1,
name: "parent1",
children: [
Children: {
id: 1,
name: "child1",
otherAttr: null
},
Children: {
id: 2,
name: "child2",
otherAttr: null
}
],
otherAttr: null
},
Parent: {
id: 2,
name: "parent2",
children: [ //size: 1
Children: {
id: null,
name: null,
otherAttr: null
}
],
otherAttr: null
}
]
这是一个错误吗?如果不是我做错了什么?
答案 0 :(得分:1)
自己遇到这个问题后,我会将GitHub issue 1677的答案放在这里以供将来参考。个别投影必须标有skipNulls()
:
Map<Long, Parent> transform = query.from(qParent)
.leftJoin(qParent.children, qChild)
.transform(GroupBy.groupBy(qParent.id)
.as(Projections.bean(Parent.class,
qParent.id,
qParent.name,
GroupBy.list(Projections.bean(Child.class,
qChild.id,
qChild.name,
Projections.bean(qSubChild.class,
qSubChild.id,
qSubChild.name).skipNulls()
.as(qChild.subChild)).skipNulls())
.as(qParent.children))));