为什么 CriteriaQuery 上的 left join 不过滤结果?
Why left join on CriteriaQuery doesn't filter results?
我有两个实体,User
和 Roles
,每个实体都具有活动布尔参数和 ManyToMany
关系。
此布尔参数用于逻辑删除。
为什么我 运行 下面的查询结果中包含非活动角色?
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<User> query = builder.createQuery(User.class);
//Select
Root<User> user = query.from(User.class);
//Join
SetJoin<User, Role> role = user.joinSet("roles", JoinType.LEFT);
Predicate rolesActivePredicate = builder.isTrue(role.get("active"));
role.on(rolesActivePredicate);
query.multiselect(user).distinct(true);
//Where
Predicate usernamePredicate = builder.equal(user.get("username"), username);
Predicate activePredicate = builder.isTrue(user.get("active"));
query.where(usernamePredicate, activePredicate);
TypedQuery<UnikUser> typedQuery = em.createQuery(query);
return Optional.of(typedQuery.getSingleResult());
- 考虑以下
User
与 Role
的 @OneToMany
关系。
User-1 : Active-Role-1, Active-Role-2, In-Active-Role-3
User-2 : In-Active-Role-3
User-3 : Active-Role-1, Active-Role-2
- JPA 首先找到
User
条满足您条件的记录(至少有一个活跃的角色)
User-1
User-3
这里就是你where条件的作用结束。一旦决定要获取哪个记录 ID,JPA 将完整获取那些 User
记录。 User-1
和 User-3
及其所有相关角色(包括非活动角色)。它可能会 join
或另一个 select
但无论何时,它都会获取所有相关字段
总而言之,一旦它决定获取 entity
,它就不能对其相关字段进行任何过滤。在这种情况下,您希望在 user.getRoles()
中过滤对象,但它不能。
如果 JPA 允许这样做,它就不能执行 dirty checking
、cascading
或 repeatable read
。所以它不允许
我有两个实体,User
和 Roles
,每个实体都具有活动布尔参数和 ManyToMany
关系。
此布尔参数用于逻辑删除。
为什么我 运行 下面的查询结果中包含非活动角色?
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<User> query = builder.createQuery(User.class);
//Select
Root<User> user = query.from(User.class);
//Join
SetJoin<User, Role> role = user.joinSet("roles", JoinType.LEFT);
Predicate rolesActivePredicate = builder.isTrue(role.get("active"));
role.on(rolesActivePredicate);
query.multiselect(user).distinct(true);
//Where
Predicate usernamePredicate = builder.equal(user.get("username"), username);
Predicate activePredicate = builder.isTrue(user.get("active"));
query.where(usernamePredicate, activePredicate);
TypedQuery<UnikUser> typedQuery = em.createQuery(query);
return Optional.of(typedQuery.getSingleResult());
- 考虑以下
User
与Role
的@OneToMany
关系。
User-1 : Active-Role-1, Active-Role-2, In-Active-Role-3
User-2 : In-Active-Role-3
User-3 : Active-Role-1, Active-Role-2
- JPA 首先找到
User
条满足您条件的记录(至少有一个活跃的角色)
User-1
User-3
这里就是你where条件的作用结束。一旦决定要获取哪个记录 ID,JPA 将完整获取那些
User
记录。User-1
和User-3
及其所有相关角色(包括非活动角色)。它可能会join
或另一个select
但无论何时,它都会获取所有相关字段总而言之,一旦它决定获取
entity
,它就不能对其相关字段进行任何过滤。在这种情况下,您希望在user.getRoles()
中过滤对象,但它不能。如果 JPA 允许这样做,它就不能执行
dirty checking
、cascading
或repeatable read
。所以它不允许