Reputation: 412
So I wanted to use projection bean in my project to optimize loading time (to avoid to get unusefull data...).
I have these two enties: Parent -----< Child (with one-to-many association)
In my database I have:
I wanted to get parent and children in one request so first I did this:
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());
It worked like a charm, the result is something like this:
[
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
}
]
But I didn't want to load the "other attributes" from child entity. So I did this query with a projection bean of Child entity:
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());
With this query, I have full control on the attributes to select. But when parent has no children, something strange happened: a Child object with all attributes set to null is present in children list like this:
[
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
}
]
Is it a bug? If not what did I do wrong??
Upvotes: 1
Views: 3167
Reputation: 6334
Having run into this myself, I'll place the answer from GitHub issue 1677 here for future reference. Individual projections must be marked with 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))));
Upvotes: 3