JPA Criteria API - 查询代码在单独执行时有效,但在用作子查询时无效
JPA Criteria API - query code works when executed separately but not when used as a subquery
我有实体 Issue
和实体 UserIssue
。 UserIssue
扩展 Issue
.
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Where(clause = "DELETED_AT IS NULL")
@Entity(name = "ISSUE")
public class Issue extends VersionedSequenceIdEntity {
... all fields
}
@Where(clause = "DELETED_AT IS NULL")
@Entity(name = "USER_ISSUE")
public class UserIssue extends Issue {
...
@Column(name = "IS_PRIVATE", nullable = false)
private Boolean isPrivate;
...
}
我正在执行子查询 以通过 sublcass 属性进行一些过滤。我的确切测试用例是我创建了三个 UserIssues。其中两个将“isPrivate”属性设置为 false。第三个是 isPrivate on true.
当我执行这个实际上只是子查询的代码时,结果包含两个基于条件的“问题”并且它是正确的
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<UserIssue> issueQuerySimple = cb.createQuery(UserIssue.class);
Root<UserIssue> issueRootSimple = issueQuerySimple.from(UserIssue.class);
issueQuerySimple.select(issueRootSimple).where(cb.isFalse(issueRootSimple.get("isPrivate")));
List<UserIssue> resultListSimple = entityManager.createQuery(issueQuerySimple).getResultList();
但是当我在上面的代码用作子查询的情况下构建整个查询时,所有三个“问题”都被 returned 并且出现了问题。我希望代码再次 return 只有两个将“isPrivate”属性设置为 false
的“问题”
CriteriaQuery<Issue> issueQuery = cb.createQuery(Issue.class);
Root<Issue> issueRoot = issueQuery.from(Issue.class);
Subquery<UserIssue> subQuery = issueQuery.subquery(UserIssue.class);
Root<UserIssue> userIssueRoot = subQuery.from(UserIssue.class);
subQuery.select(userIssueRoot).where(cb.isFalse(userIssueRoot.get("isPrivate")));
issueQuery.select(issueRoot).where(cb.exists(subQuery));
List<Issue> resultList = entityManager.createQuery(issueQuery).getResultList();
在这里您还可以看到来自休眠创建的日志的查询。这对我来说似乎是正确的
select
issue0_.id as id2_2_,
issue0_.deleted_at as deleted_3_2_,
issue0_.created_when as created_4_2_,
issue0_.created_by as created_5_2_,
issue0_.updated_when as updated_6_2_,
issue0_.version as version7_2_,
issue0_.application_id as applicat8_2_,
issue0_.version_id as version_9_2_,
issue0_.organization_id as organiz10_2_,
issue0_.severity as severit11_2_,
issue0_.state as state12_2_,
issue0_.title as title13_2_,
issue0_.type_id as type_id18_2_,
issue0_.updated_by_customer_at as updated14_2_,
issue0_.assigned_to as assigne15_2_,
issue0_.description as descrip16_2_,
issue0_.is_private as is_priv17_2_,
issue0_.dtype as dtype1_2_
from
issue issue0_
where
(
issue0_.DELETED_AT IS NULL
)
and (
exists (
select
userissue1_.id
from
issue userissue1_
where
userissue1_.dtype='UserIssue'
and (
userissue1_.DELETED_AT IS NULL
)
and userissue1_.is_private=0
)
)
那么,为什么基于子类字段的过滤不起作用,它 return 是所有三个实例而不是两个?有什么问题或我看不到什么?
非常感谢
替换
issueQuery.select(issueRoot).where(cb.exists(subQuery));
和
issueQuery.select(issueRoot).where(issueRoot.get("id").in(subQuery));
说明
- 从sql查询可以看出,只要一个
userissue
和is_private=0
存在,就会select 所有 issue
s
- 这不是您想要的行为。您仍然必须使用子查询,但想用
issue0_.id in
替换 exists
并且此代码片段会执行此操作
我有实体 Issue
和实体 UserIssue
。 UserIssue
扩展 Issue
.
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Where(clause = "DELETED_AT IS NULL")
@Entity(name = "ISSUE")
public class Issue extends VersionedSequenceIdEntity {
... all fields
}
@Where(clause = "DELETED_AT IS NULL")
@Entity(name = "USER_ISSUE")
public class UserIssue extends Issue {
...
@Column(name = "IS_PRIVATE", nullable = false)
private Boolean isPrivate;
...
}
我正在执行子查询
当我执行这个实际上只是子查询的代码时,结果包含两个基于条件的“问题”并且它是正确的
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<UserIssue> issueQuerySimple = cb.createQuery(UserIssue.class);
Root<UserIssue> issueRootSimple = issueQuerySimple.from(UserIssue.class);
issueQuerySimple.select(issueRootSimple).where(cb.isFalse(issueRootSimple.get("isPrivate")));
List<UserIssue> resultListSimple = entityManager.createQuery(issueQuerySimple).getResultList();
但是当我在上面的代码用作子查询的情况下构建整个查询时,所有三个“问题”都被 returned 并且出现了问题。我希望代码再次 return 只有两个将“isPrivate”属性设置为 false
的“问题”CriteriaQuery<Issue> issueQuery = cb.createQuery(Issue.class);
Root<Issue> issueRoot = issueQuery.from(Issue.class);
Subquery<UserIssue> subQuery = issueQuery.subquery(UserIssue.class);
Root<UserIssue> userIssueRoot = subQuery.from(UserIssue.class);
subQuery.select(userIssueRoot).where(cb.isFalse(userIssueRoot.get("isPrivate")));
issueQuery.select(issueRoot).where(cb.exists(subQuery));
List<Issue> resultList = entityManager.createQuery(issueQuery).getResultList();
在这里您还可以看到来自休眠创建的日志的查询。这对我来说似乎是正确的
select
issue0_.id as id2_2_,
issue0_.deleted_at as deleted_3_2_,
issue0_.created_when as created_4_2_,
issue0_.created_by as created_5_2_,
issue0_.updated_when as updated_6_2_,
issue0_.version as version7_2_,
issue0_.application_id as applicat8_2_,
issue0_.version_id as version_9_2_,
issue0_.organization_id as organiz10_2_,
issue0_.severity as severit11_2_,
issue0_.state as state12_2_,
issue0_.title as title13_2_,
issue0_.type_id as type_id18_2_,
issue0_.updated_by_customer_at as updated14_2_,
issue0_.assigned_to as assigne15_2_,
issue0_.description as descrip16_2_,
issue0_.is_private as is_priv17_2_,
issue0_.dtype as dtype1_2_
from
issue issue0_
where
(
issue0_.DELETED_AT IS NULL
)
and (
exists (
select
userissue1_.id
from
issue userissue1_
where
userissue1_.dtype='UserIssue'
and (
userissue1_.DELETED_AT IS NULL
)
and userissue1_.is_private=0
)
)
那么,为什么基于子类字段的过滤不起作用,它 return 是所有三个实例而不是两个?有什么问题或我看不到什么?
非常感谢
替换
issueQuery.select(issueRoot).where(cb.exists(subQuery));
和
issueQuery.select(issueRoot).where(issueRoot.get("id").in(subQuery));
说明
- 从sql查询可以看出,只要一个
userissue
和is_private=0
存在,就会select 所有issue
s - 这不是您想要的行为。您仍然必须使用子查询,但想用
issue0_.id in
替换exists
并且此代码片段会执行此操作