如何正确判断一个“存在”是否存在? JPA Criteria 查询子句返回 true 还是 false?

发布于 2024-11-25 01:20:22 字数 1300 浏览 1 评论 0原文

我不知道如何执行返回布尔输出的 JPA 标准查询。

目标是拥有一个在 Oracle 中执行时看起来像这样的条件查询:

select 1 from dual where exists ( ... );

我使用子查询执行的 where isn't (...) 部分。我正在努力应对外部查询。

其实际用途是确定 exists 子句中的子查询返回 true 还是 false

这就是我所写的:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
 
CriteriaQuery<Object> query = criteriaBuilder.createQuery();
query.from(Boolean.class);
query.select(criteriaBuilder.literal(true));

Subquery<Location> subquery = query.subquery(Location.class);
Root<Location> subRootEntity = subquery.from(Location.class);
subquery.select(subRootEntity);

Path<?> attributePath = subRootEntity.get("State");
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX"));
subquery.where(predicate);
query.where(criteriaBuilder.exists(subquery));
 
TypedQuery<Object> typedQuery = em.createQuery(query);

最后一行抛出一个错误,指出“布尔值不是实体”。我认为我的问题是不知道如何表达查询的“from”部分,以便结果输出 1 或 0/ true 或 false - 而不是实体。

我知道我可以检索任何实体,然后检查结果列表的大小是否为 1。

我问如何获得布尔结果,既可以避免检索这些列的不必要的任务,也可以学习如何执行此操作。

这可能吗?

谢谢! 爱德华多

I don't know how to perform a JPA criteria query that returns with a boolean output.

The goal is to have a criteria query that looks like this when executed in Oracle:

select 1 from dual where exists ( ... );

The where exists (...) part I performed with a subquery. I'm struggling with the external query.

The practical use of this is to determine whether that subquery in the exists clause returns true or false.

This is what I've written:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
 
CriteriaQuery<Object> query = criteriaBuilder.createQuery();
query.from(Boolean.class);
query.select(criteriaBuilder.literal(true));

Subquery<Location> subquery = query.subquery(Location.class);
Root<Location> subRootEntity = subquery.from(Location.class);
subquery.select(subRootEntity);

Path<?> attributePath = subRootEntity.get("State");
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX"));
subquery.where(predicate);
query.where(criteriaBuilder.exists(subquery));
 
TypedQuery<Object> typedQuery = em.createQuery(query);

The last line throws an error, stating that "Boolean is not an entity". I think my issue is not knowing how to express the "from" part of the query so that the result outputs 1 or 0/ true or false - not an entity.

I know I could retrieve any entity and then check if the list of results has size of 1.

I'm asking how to get a boolean result, both to avoid the unnecessary task of retrieving those columns and also to learn how to do it.

Is this possible at all?

Thanks!
Eduardo

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

寄离 2024-12-02 01:20:23

您可以对一个属性(例如 ID)进行选择,并将返回的最大结果设置为 1,以便确保数据库不会执行不必​​要的工作(例如对所有实例进行计数)。那么您的结果列表要么为空(exists = false),要么只有一个元素(exists = true)。

You could do a select for one property (e.g. the ID) and set the max results returned to 1 so that you make sure the DB does not do more work than necessary (like counting all instances). Then your results list will either be empty (exists = false) or have one element (exists = true).

各空 2024-12-02 01:20:23

我知道这是一个较旧的问题,但对于其他人来说:如何尝试使用 Spring 的 jpa @Query 注释和选择案例查询(取决于您的数据库实现)以及返回布尔值的方法。例如(MySQL):

@Query("SELECT CASE WHEN COUNT(l) > 0 THEN TRUE ELSE FALSE END FROM Location l WHERE l.state=?1")
boolean locationForStateExists(String state);

有时,当指定的 JPA 或查询构建器方法不能完全按照您的要求执行时,仅使用 @Query 中的查询字符串就可以成为救星。

I know this is an older question, but for anyone else looking: How about trying to use Spring's jpa @Query annotation and a select case query (depending on your db implementation) with a method that returns a boolean. For example (MySQL):

@Query("SELECT CASE WHEN COUNT(l) > 0 THEN TRUE ELSE FALSE END FROM Location l WHERE l.state=?1")
boolean locationForStateExists(String state);

Sometimes just using the query string in @Query can be a life saver when the named JPA or query builder methods don't quite do what you want them to.

心舞飞扬 2024-12-02 01:20:23

基于 dimo 答案 并在 user3158918回答

EntityManager em = ...;

val cb = em.getCriteriaBuilder();
val query = cb.createQuery(Integer.class);
val root = query.from(YourEntity.class);

val predicate = cb.equal(root.get(attribute), attributeValue);

query.select(cb.literal(1)).where(predicate);

return !em.createQuery(query).setMaxResults(1).getResultList().isEmpty();

我用了lombok来清洁。
此代码生成 SQL 查询:

SELECT 1 FROM your_entity_table WHERE your_entity_table.attribute = attributeValue LIMIT 1

请发布您的解决方案,如果它更快......

The maximum optimized and full solution for existance checking via Criteria API based on dimo answer and with help of user3158918 answer:

EntityManager em = ...;

val cb = em.getCriteriaBuilder();
val query = cb.createQuery(Integer.class);
val root = query.from(YourEntity.class);

val predicate = cb.equal(root.get(attribute), attributeValue);

query.select(cb.literal(1)).where(predicate);

return !em.createQuery(query).setMaxResults(1).getResultList().isEmpty();

I used a lombok to be clean.
This code generates SQL query:

SELECT 1 FROM your_entity_table WHERE your_entity_table.attribute = attributeValue LIMIT 1

Please post your solution, if its faster...

与他有关 2024-12-02 01:20:23

我认为问题是 query.from(Boolean.class)。它尝试创建“从布尔值选择对象”查询。如果您想要布尔值作为返回类型,则需要使用

CriteriaQuery<Boolean> query = criteriaBuilder.createQuery(Boolean.class)

然后从任何现有实体表查询来创建有效的查询(可能来自子查询的表)。我不认为从对偶创建有效,除非您设法映射对偶表。

I think the problem is the the query.from(Boolean.class). It tries to create a "select object from boolean" query. If you want a boolean as return type you need to use

CriteriaQuery<Boolean> query = criteriaBuilder.createQuery(Boolean.class)

Then query from any existing entity table to create a valid query (perhaps from the subquery's table). I don't think that create from dual works except if you managed to map the dual table.

丢了幸福的猪 2024-12-02 01:20:23

有什么理由要求所有逻辑都必须在 JPA 中吗?如果不是,为什么不使用 SELECT COUNT 然后使用条件来设置布尔值?

Boolean exists = false;
int count = selectCountQuery();
if (count > 0) {
  exists = true;
}

Is there any reason that all the logic has to be in JPA? If not, why not use SELECT COUNT and then a conditional to set the boolean?

Boolean exists = false;
int count = selectCountQuery();
if (count > 0) {
  exists = true;
}
牵你的手,一向走下去 2024-12-02 01:20:22

是的,这是可能的。假设您有一个与 dual 表相对应的实体,您将需要在 CriteriaQuery#from 中使用该实体类。

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

CriteriaQuery<Boolean> query = criteriaBuilder.createQuery(Boolean.class);
query.from(dual.class);
query.select(criteriaBuilder.literal(true));

Subquery<Location> subquery = query.subquery(Location.class);
Root<Location> subRootEntity = subquery.from(Location.class);
subquery.select(subRootEntity);

Path<?> attributePath = subRootEntity.get("State");
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX"));
subquery.where(predicate);
query.where(criteriaBuilder.exists(subquery));

TypedQuery<Boolean> typedQuery = em.createQuery(query);

Yes, this is possible. Assuming that you have an entity corresponding to your dual table, you will want to use that entity class in CriteriaQuery#from.

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

CriteriaQuery<Boolean> query = criteriaBuilder.createQuery(Boolean.class);
query.from(dual.class);
query.select(criteriaBuilder.literal(true));

Subquery<Location> subquery = query.subquery(Location.class);
Root<Location> subRootEntity = subquery.from(Location.class);
subquery.select(subRootEntity);

Path<?> attributePath = subRootEntity.get("State");
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX"));
subquery.where(predicate);
query.where(criteriaBuilder.exists(subquery));

TypedQuery<Boolean> typedQuery = em.createQuery(query);
始于初秋 2024-12-02 01:20:22

Hibernate 5 正在运行:

Subquery<Integer> subquery = query.subquery(Integer.class);
Root<Location> subRootEntity = subquery.from(Location.class);
subquery.select(criteriaBuilder.literal(1));

Path<?> attributePath = subRootEntity.get("State");
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX"));
subquery.where(predicate);
query.where(criteriaBuilder.exists(subquery));

Hibernate 5 is working:

Subquery<Integer> subquery = query.subquery(Integer.class);
Root<Location> subRootEntity = subquery.from(Location.class);
subquery.select(criteriaBuilder.literal(1));

Path<?> attributePath = subRootEntity.get("State");
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX"));
subquery.where(predicate);
query.where(criteriaBuilder.exists(subquery));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文