La manera correcta de determinar si «existe» JPA Criterios de la cláusula de Consulta devuelve verdadero o falso?

No sé cómo realizar un JPA criterios de consulta que devuelve un booleano de salida.

El objetivo es tener una consulta de criterios que se parece a esto cuando se representan en Oracle:

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

La where exists (...) parte he realizado con una subconsulta. Yo estoy luchando con la consulta externa.

El uso práctico de esto es determinar si esa subconsulta en la exists cláusula devuelve true o false.

Esto es lo que he escrito:

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);

La última línea de salidas de un error, afirmando que «Boolean no es una entidad«. Creo que mi problema es no saber cómo expresar el «de» parte de la consulta, de modo que el resultado de las salidas 1 o 0/verdadero o falso – no una entidad.

Sé que podría recuperar cualquier entidad y, a continuación, compruebe si la lista de resultados tiene un tamaño de 1.

Estoy preguntando cómo conseguir un resultado booleano, tanto para evitar la innecesaria tarea de recuperar las columnas y también para aprender cómo hacerlo.

Es esto posible?

Gracias!
Eduardo

No no se puede directamente hacer eso, pero de una forma común es comprobar que el conde de conjunto de resultados que yo.e si el recuento es mayor que cero, entonces la verdadera persona falsa.

OriginalEl autor Edy Bourne | 2011-07-18

6 Kommentare

  1. 7

    Usted podría hacer un select de una propiedad (por ejemplo, el ID) y establecer el máximo de resultados devueltos a 1, así que asegúrese de que la DB no trabajar más de lo necesario (como el conteo de todas las instancias). A continuación, la lista de resultados será vacía (existe = false) o tienen un elemento (existe = true).

    Esto es lo que yo estaba buscando, una manera de lograr eso sin tener el DBMS trabaje más de lo necesario. Gracias!!

    OriginalEl autor dimo

  2. 10

    Sí, esto es posible. Asumiendo que usted tiene una entidad correspondiente a su dual tabla, usted querrá usar esa clase de entidad en 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);

    OriginalEl autor Matthew T. Staebler

  3. 2

    Sé que esta es una antigua pregunta, pero para una persona que quiere: ¿y tratando de usar Spring, jpa Consulta @anotación y seleccione un caso de consulta (dependiendo de tu db implementación) con un método que devuelve un valor booleano. Por ejemplo (MySQL):

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

    A veces, sólo el uso de la cadena de consulta en Consulta @puede ser un ahorrador de vida cuando el nombre de la app o el generador de consultas de los métodos de no hacer lo que usted desea.

    Este se basa en count(), que es el problema fundamental. Hibernate no apoyo la exists palabra clave excepto en el interior de la where cláusula, que no lograr lo que el OP está pidiendo. La selección de un count podría potencialmente ser extremadamente lento (dependiendo de la complejidad de la where cláusula, la presencia de índices, etc.) mientras que un exists cláusula rápido fallar en la primera aparición. Es realmente una vergüenza JPA/Hibernate no admite esta trivial de optimización.

    OriginalEl autor David P

  4. 2

    Hibernate 5 está trabajando:

    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));
    Gracias por la actualización!

    OriginalEl autor user3158918

  5. 0

    Creo que el problema es el de la consulta.a partir de(Boolean.class). Se intenta crear un «seleccione el objeto de booleanos» de la consulta. Si quieres un booleano como tipo de retorno que usted necesita para utilizar

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

    Luego de la consulta de cualquier entidad de la tabla para crear una consulta válida (tal vez de la subconsulta de la tabla). No creo que crear desde la doble funciona, excepto si se las arregló para asignar el doble de la tabla.

    OriginalEl autor user948392

  6. -3

    ¿Hay alguna razón por la que toda la lógica tiene que ser en JPA? Si no, ¿por qué no utilizar SELECCIONE la cuenta y, a continuación, un condicional para establecer el booleano?

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

    OriginalEl autor Chip McCormick

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea