¿cómo puedo establecer una Hibernación Parámetro a «null»? Ejemplo:

Query query = getSession().createQuery("from CountryDTO c where c.status = :status  and c.type =:type")
.setParameter("status", status, Hibernate.STRING)
.setParameter("type", type, Hibernate.STRING);

En mi caso, el estado de la Cadena puede ser null. He depurado este y de hibernación, a continuación, genera una cadena SQL/consulta como esta ….status = null… Sin embargo, esto no funciona en MYSQL, como la correcta instrucción SQL debe ser «status is null» (Mysql no entiende estado=null y se evalúa a false para que no se deja constancia de que alguna vez será devuelto por la consulta, de acuerdo a la mysql docs que he leído…)

Mis Preguntas:

  1. ¿Por qué no Hibernate traducir una cadena nula correctamente que «es nulo» (y bastante y erróneamente crea «=null»)?

  2. ¿Cuál es la mejor manera de volver a escribir esta consulta, por lo que es nulo-seguro? Con nullsafe me refiero a que en el caso de que el «estado» de la Cadena es nula de que se debe crear un «es nulo»?

Muchas gracias!
Tim

  • Para allo aquellos interesados en una solución creo que los Criterios de la API es una manera de ir. Pero aún no estoy muy convencido de como se bloads el código horriblemente y el uso de HQL sería mucho más limpio. Tal vez la Solución real está en la implementación de su propio Tipo de Hibernate (he implementado una de las Enumeraciones pero estos auto-aplicado los Tipos, al menos los básicos tienen grandes desventajas respecto a la bulid en los tipos de hibernate en Consulta con HQL (a menos que también extender el HQL analizador?) lo que hace de este un gran projekt y requiere una gran cantidad de Hibernate conocimientos…(continúa en la parte 2)
  • Parte2: tal vez la forma más fácil (en el otro lado definitivamente NO es una Mejor Práctica) es directamente edición de la Hibernación Tipo de Cadena de la clase en sí y agregar la falta de lógica. Esto sólo debería ser un punto de vista de líneas para comprobar el valor null de la Cadena de valores y actuar en consecuencia…
  • Solo encontré con esto también…mi dios esto es braindead.
  • Creo, en serio, odio hibernate, esto es absolutamente estúpido
  • Así que todos estos años más tarde, hay una solución a este pero sin el uso de la API de Criterios?
  • No puedo creer que todavia no hay!

InformationsquelleAutor tim | 2010-01-23

10 Comentarios

  1. 39
    1. Creo hibernate primera se traduce a su consulta HQL a SQL y sólo después de que se intenta enlazar sus parámetros. Lo que significa que no será capaz de reescribir la consulta de param = ? a param is null.

    2. Trate de usar api de Criterios:

      Criteria c = session.createCriteria(CountryDTO.class);
      c.add(Restrictions.eq("type", type));
      c.add(status == null ? Restrictions.isNull("status") : Restrictions.eq("status", status));
      List result = c.list();
    • Hola Sergey, Gracias por tu respuesta. De hecho, me implementado (ya antes de publicar tu respuesta) también con los Criterios de la API. Pero yo sin embargo creo que esto no es la «solución ideal» para el problema. Ok, para ser honesto, a veces «rarezas/bugs» no tiene una buena solución….He marcado en su respuesta como la «solución» para el problema.
    • usted es bienvenido 🙂 pero, ¿qué puede esperar de la solución ideal? si usted está bien con criterios de api en lugar de hql, siempre puedes crear tu propio método de fábrica para ‘null-segura» de Criterio.
    • Gran respuesta! Esta solución simple, me ayudó a consulta en un campo acepta valores null sin recurrir a la cadena de creación de la consulta!
  2. 28

    Esto no es una Hibernación tema específico (es sólo SQL de la naturaleza), y SÍ, hay una solución para SQL y HQL:

    @Peter Lang tenía la idea correcta, y tenía la correcta consulta HQL. Supongo que sólo necesitaba una nueva carrera limpia para recoger la consulta de los cambios 😉

    El código de abajo, absolutamente funciona y es bueno tener todas tus consultas en orm.xml

    from CountryDTO c where ((:status is null and c.status is null) or c.status = :status) and c.type =:type

    Si su Cadena de parámetro es null, la consulta va a comprobar si la fila es el estado de null así. De lo contrario, se va a recurrir a comparar con el signo de igual.

    Notas:

    El problema puede ser específico de MySql capricho. Yo sólo he probado con Oracle.

    La consulta anterior se asume que hay filas de la tabla donde c.el estado es nulo

    La cláusula where es una prioridad para que el parámetro se comprueba primero.

    El nombre de parámetro «tipo» puede ser una palabra reservada de SQL pero no importa ya que es reemplazado antes de que se ejecuta la consulta.

    Si usted necesita para saltar la :estado de where_clause por completo; se puede codificar como:

    from CountryDTO c where (:status is null or c.status = :status) and c.type =:type

    y es equivalente a:

    sql.append(" where ");
    if(status != null){
      sql.append(" c.status = :status and ");
    }
    sql.append(" c.type =:type ");
    • ¿por qué no from CountryDTO c where (:status is not null and c.status = :status) and c.type =:type ?
    • Con or la consulta de rendimiento: from CountryDTO c where (true) and c.type =:type y el tuyo rendimiento: from CountryDTO c where (false) and c.type =:type, que le dará no hay filas.
    • También puede probar este: select 'data' from dual where (1=2) y este: select 'data' from dual where (1=1) para ver la diferencia.
  3. 13

    La javadoc para setParameter(String, Object) es explícita, diciendo que el valor del Objeto debe ser no nulo. Es una lástima que no se lance una excepción si se pasa un valor null en, aunque.

    Una alternativa es setParameter(String, Object, Tipo), que hace permitir valores nulos, aunque no estoy seguro de lo que Type parámetro sería más apropiado aquí.

    • Hola skaffman. Muchas gracias por su ayuda! Cuando la pregunta en realidad pensé yo soy sólo a la tonta para encontrar una solución. Pero su parece que este es un verdadero «rareza» de hibernación. Más probable es que tengo que escribir mi propia aceptan valores null-de Tipo Cadena o voy a tener que cambiar a los Criterios de las Consultas… Después de cavar más profundo, parece que la implementación actual de la Hibernat.Tipo de CADENA no acepta valores null: docjar.com/html/api/org/hibernate/type/StringType.java.html. (Pero no el de MySQL JConnector implementar el PreparedStatment.setString correctamente??) Gracias Tim.
    • Sólo para información, es en realidad una «característica» de JDBC: bugs.sun.com/bugdatabase/view_bug.do?bug_id=4312435 Hibernate utiliza JDBC del PreparedStatement.setNull() para enlazar null parámetros
  4. 5

    Parece que usted tiene que utilizar is null en el HQL, (que puede conducir a la compleja permutaciones si hay más de uno de los parámetros con el valor potencial.) pero aquí hay una posible solución:

    String statusTerm = status==null ? "is null" : "= :status";
    String typeTerm = type==null ? "is null" : "= :type";
    
    Query query = getSession().createQuery("from CountryDTO c where c.status " + statusTerm + "  and c.type " + typeTerm);
    
    if(status!=null){
        query.setParameter("status", status, Hibernate.STRING)
    }
    
    
    if(type!=null){
        query.setParameter("type", type, Hibernate.STRING)
    }
    • Se ve como en los viejos consulta sql edificio a mí. Se adhieren a los criterios de la api para cosas como esta. Escrito a mano hql es muy propenso a errores.
  5. 4

    Yo no intente esto, pero ¿qué sucede cuando se utiliza :status dos veces para comprobar NULL?

    Query query = getSession().createQuery(
         "from CountryDTO c where ( c.status = :status OR ( c.status IS NULL AND :status IS NULL ) ) and c.type =:type"
    )
    .setParameter("status", status, Hibernate.STRING)
    .setParameter("type", type, Hibernate.STRING);
    • El síndrome de Peter, muchas gracias por tu ayuda! No sé por qué, pero parece que hibernan siempre se evalúa el c.= estado :estado de O ( c.el estado ES NULO Y :el estado ES NULO ) a.c.estado = null (según mi mysql query log). También he cambiado el orden de a (( c.el estado ES NULO Y :el estado ES NULO ) O c.estado= 🙂 con el mismo resultado. Tim Gracias
  6. 4

    HQL apoya se unen, permitiendo feo soluciones como:

    where coalesce(c.status, 'no-status') = coalesce(:status, 'no-status')
  7. 1

    Puede utilizar

    Restrictions.eqOrIsNull("status", status)

    lugar de

    status == null ? Restrictions.isNull("status") : Restrictions.eq("status", status)
  8. 1

    Aquí está la solución que he encontrado en Hibernación 4.1.9. Tuve que pasar un parámetro a mi consulta que puede tener valor NULO a veces. Así que me pasé el uso de:

    setParameter("orderItemId", orderItemId, new LongType())

    Después de eso, yo uso la siguiente cláusula where en la consulta:

    where ((:orderItemId is null) OR (orderItem.id != :orderItemId))

    Como se puede ver, estoy usando la Consulta.setParameter(String, Object, Tipo) método, que no podía usar la Hibernación.LARGO que he encontrado en la documentación (probablemente que era en versiones anteriores). Un conjunto completo de opciones de tipo de parámetro, consulte la lista de la clase de implementación de la org.hibernate.tipo.Tipo de interfaz.

    Espero que esto ayude!

  9. -1

    esto parece funcionar como wel ->

    @Override
    public List<SomeObject> findAllForThisSpecificThing(String thing) {
        final Query query = entityManager.createQuery(
                "from " + getDomain().getSimpleName() + " t  where t.thing = " + ((thing == null) ? " null" : " :thing"));
        if (thing != null) {
            query.setParameter("thing", thing);
        }
        return query.getResultList();
    }

    Por cierto, soy bastante nuevo en esto, así que si por cualquier razón esto no es una buena idea, que me haga saber. Gracias.

    • ¿No deberías estar usando el is operador: es decir, ... + " t where t.thing " + ((thing == null) ? "is null" : "= :thing")
    • Podría usted comentar la diferencia entre los dos?
    • El uso de = null hará una excepción. Aunque puede depender del dbms de ejecutar este. En SQL tiene el mismo problema, también hay que utilizar is null y no = null. La cosa con null es que algunas bases de datos respecto de que no se realmente como un valor para el vacío, sino más bien como un valor indeterminado, lo que significa que null no es igual a null. Para ello el null = null nunca sería cierto. Ver: stackoverflow.com/questions/5066492/…

Dejar respuesta

Please enter your comment!
Please enter your name here