JPA 在使用 selectcase 构造查询时处理空值
JPA handling of null values in construct query with selectcase
我有三个实体和一个三元关系。
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",其中包含属于用户的用户组和角色。
这是我写的代码。当组不为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();
我面临的问题是当组确实为空时,如在我的测试数据中,我只得到四个角色组 return。
如果我切换 when 和 otherwise 情况,我什至会得到一个 SerializationException。
我是不是误解了 selectCase?
使用 User2Role2Group_.group
创建一个内部联接,根据定义,只有在 USER_GROUP_ID
字段包含非 null
值时才联接。
向您的查询添加显式连接并将其标记为左连接以获取 null
值。我还没有测试代码,但像这样的东西应该会让你继续。
Join<User2Role2Group, Group> join = from.join(User2Role2Group_.group, JoinType.LEFT);
我有三个实体和一个三元关系。
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",其中包含属于用户的用户组和角色。
这是我写的代码。当组不为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();
我面临的问题是当组确实为空时,如在我的测试数据中,我只得到四个角色组 return。
如果我切换 when 和 otherwise 情况,我什至会得到一个 SerializationException。
我是不是误解了 selectCase?
使用 User2Role2Group_.group
创建一个内部联接,根据定义,只有在 USER_GROUP_ID
字段包含非 null
值时才联接。
向您的查询添加显式连接并将其标记为左连接以获取 null
值。我还没有测试代码,但像这样的东西应该会让你继续。
Join<User2Role2Group, Group> join = from.join(User2Role2Group_.group, JoinType.LEFT);