JPA使用selectcase

时间:2017-05-12 09:40:27

标签: java jpa criteria-api

我有三个实体和一个三元关系。

    public class User{}
    public class UserGroup{}
    public class Role{}
    public class User2Role2Group{
        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "USER_ID", nullable = false)
        private User user;

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "ROLE_ID", nullable = false)
        private Role role;

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "USER_GROUP_ID")
        private UserGroup group;
    }

User2Role2Group的组可以为空。

这是我的测试用例数据。

+----------+----------------+---------+---------+ | URG_ID | USER_GROUP_ID | USER_ID | ROLE_ID | +----------+----------------+---------+---------+ | urg_id1 | user_group_id1 | userId | roleID1 | | urg_id2 | user_group_id2 | userId | roleID1 | | urg_id3 | null | userId | roleID1 | | urg_id4 | user_group_id2 | userId | roleID2 | | urg_id5 | user_group_id1 | userId | roleID2 | +----------+----------------+---------+---------+

现在我想构建一个值对象“RoleGroup”列表,其中包含属于用户的UserGroups和Roles。

这是我写的代码。当该组不为null时,我将在数据库中找到该组,否则我将为UserGroup构建一个nullliteral。

    final CriteriaBuilder builder = em.getCriteriaBuilder();
    final CriteriaQuery<RoleGroup> criteria = builder.createQuery(RoleGroup.class);
    final Root<User2Role2Group> from = criteria.from(User2Role2Group.class);
    criteria.select(builder.construct(RoleGroup.class, from.get(User2Role2Group_.role),
            builder.selectCase()
                    .when(builder.isNotNull(from.get(User2Role2Group_.group)), from.get(User2Role2Group_.group))
                    .otherwise(builder.nullLiteral(UserGroup.class))));
    criteria.where(builder.equal(from.get(User2Role2Group_.user).get(User_.userId), userId));
    final TypedQuery<RoleGroup> query = em.createQuery(criteria);
    return query.getResultList();

我面临的问题是当组确实为null时,就像在我的testdata中一样,我只返回四个RoleGroups。

如果我切换时间和其他情况我甚至会得到一个SerializationException。

我是否误解了selectCase?

1 个答案:

答案 0 :(得分:2)

使用User2Role2Group_.group创建一个内部联接,根据定义,只有USER_GROUP_ID字段包含非null值时才会加入。

为您的查询添加显式联接,并将其标记为左联接以获取null值。我还没有对代码进行测试,但是这样的事情可以让你继续。

Join<User2Role2Group, Group> join = from.join(User2Role2Group_.group, JoinType.LEFT);