QueryDsl:来自oneToMany与投影bean的关联的null实体

时间:2015-11-27 14:34:02

标签: hibernate jpa javabeans querydsl

所以我想在我的项目中使用投影bean来优化加载时间(以避免获得无用的数据......)。

我有这两个内容:父母-----<孩子(与一对多的关联)

在我的数据库中,我有:

  • parent1 with child1 and child2
  • parent2 witout children

我想在一个请求中得到父母和孩子,所以首先我这样做了:

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
    }
]

这是一个错误吗?如果不是我做错了什么?

1 个答案:

答案 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))));