¿Cómo evitar las advertencias de seguridad de tipo con los resultados de Hibernate HQL?

votos
91

Por ejemplo, tengo esa consulta:

Query q = sess.createQuery(from Cat cat);
List cats = q.list();

Si trato de hacer algo como esto, aparecerá la advertencia Tipo de seguridad: la expresión del tipo Lista necesita conversión no verificada para cumplir con la Lista:

List<Cat> cats = q.list();

¿Hay alguna forma de evitarlo?

Publicado el 22/09/2008 a las 16:53
fuente por usuario
En otros idiomas...                            


16 respuestas

votos
5

En nuestro código anotamos los métodos de llamada con:

@SuppressWarnings ("desmarcado")

Sé que parece un truco, pero un co-desarrollador comprobó recientemente y descubrió que era todo lo que podíamos hacer.

Respondida el 22/09/2008 a las 16:57
fuente por usuario

votos
2

No, pero puede aislarlo en métodos de consulta específicos y suprimir las advertencias con una @SuppressWarnings("unchecked")anotación.

Respondida el 22/09/2008 a las 16:58
fuente por usuario

votos
-5

Si no desea usar @SuppressWarnings ("desmarcado"), puede hacer lo siguiente.

   Query q = sess.createQuery("from Cat cat");
   List<?> results =(List<?>) q.list();
   List<Cat> cats = new ArrayList<Cat>();
   for(Object result:results) {
       Cat cat = (Cat) result;
       cats.add(cat);
    }

FYI - Creé un método util que hace esto por mí para que no ensucie mi código y no tenga que usar @SupressWarning.

Respondida el 22/09/2008 a las 17:34
fuente por usuario

votos
0

La solución de Joe Dean parece interesante, pero ¿cree que vale la pena? ¿Crear una nueva lista y recorrer todos los elementos solo para deshacerse de las advertencias?

(Lo siento, no puedo agregar un comentario directamente a su solución por alguna razón)

Respondida el 22/09/2008 a las 17:48
fuente por usuario

votos
21

También lo usamos @SuppressWarnings("unchecked"), pero a menudo tratamos de usarlo solo en la declaración de la variable, no en el método como un todo:

public List<Cat> findAll() {
    Query q = sess.createQuery("from Cat cat");
    @SuppressWarnings("unchecked")
    List<Cat> cats = q.list();
    return cats;
}
Respondida el 22/09/2008 a las 17:55
fuente por usuario

votos
93

Usar en @SuppressWarningstodas partes, como se sugiere, es una buena manera de hacerlo, aunque implica un poco de digitación de los dedos cada vez que llamas q.list().

Hay otras tres técnicas que sugeriría:

Collections.checkedList()

Reemplaza tu tarea con esto:

List<Cat> cats = Collections.checkedList(q.list(), Cat.class);

Es posible que desee comprobar el javadoc para ese método , especialmente en lo que respecta a equalsy hashCode.

Escribir un cast-helper

Simplemente refactorice todo @SuppressWarningsen un solo lugar:

List<Cat> cats = MyHibernateUtils.listAndCast(q);

...

public static <T> List<T> listAndCast(Query q) {
    @SuppressWarnings("unchecked")
    List list = q.list();
    return list;
}

Evitar que Eclipse genere advertencias para problemas inevitables

En Eclipse, vaya a Ventana> Preferencias> Java> Compilador> Errores / Advertencias y en Tipo genérico, seleccione la casilla de verificación Ignore unavoidable generic type problems due to raw APIs

Esto desactivará las advertencias innecesarias de problemas similares a los descritos anteriormente que son inevitables.

Algunos comentarios:

  • Elegí pasar Queryel resultado en lugar de q.list()porque de esa manera este método de "trampa" solo puede usarse para hacer trampa con Hibernate, y no para hacer trampas Listen general.
  • Puede agregar métodos similares para .iterate()etc.
Respondida el 23/09/2008 a las 04:38
fuente por usuario

votos
1

Tuvimos el mismo problema. Pero no fue un gran problema para nosotros porque tuvimos que resolver otros problemas más importantes con Hibernate Query y Session.

Específicamente:

  1. controlar cuándo se puede comprometer una transacción. (Queríamos contar cuántas veces se "inició" un tx y solo confirmar cuando el tx se "terminó" la misma cantidad de veces que se inició. Útil para código que no sabe si necesita iniciar una transacción. cualquier código que necesite un tx simplemente "comience" uno y lo finaliza cuando termine).
  2. Recopilación de métricas de rendimiento
  3. Retrasar el inicio de la transacción hasta que se sepa que algo realmente se hará.
  4. Comportamiento más suave para query.uniqueResult ()

Entonces para nosotros, tenemos:

  1. Crear una interfaz (AmplafiQuery) que extienda Query
  2. Cree una clase (AmplafiQueryImpl) que amplíe AmplafiQuery y que contenga un org.hibernate.Query
  3. Crea un Txmanager que devuelva un Tx.
  4. Tx tiene los diversos métodos CreateQuery y devuelve AmplafiQueryImpl

Y por último,

AmplafiQuery tiene un "asList ()" que es una versión habilitada genérica de Query.list () AmplafiQuery tiene un "único ()" que es una versión habilitada genérica de Query.uniqueResult () (y simplemente registra un problema en lugar de arrojar un excepción)

Esto es mucho trabajo para evitar @SuppressWarnings. Sin embargo, como dije (y enumeré) ¡hay muchos otros mejores! razones para hacer el trabajo de envolver.

Respondida el 13/02/2009 a las 03:08
fuente por usuario

votos
4

No es un descuido o un error. La advertencia refleja un problema subyacente real: no hay forma de que el compilador de Java pueda estar seguro de que la clase de hibernación hará su trabajo correctamente y de que la lista que devuelve solo contendrá Gatos. Cualquiera de las sugerencias aquí está bien.

Respondida el 13/02/2009 a las 03:55
fuente por usuario

votos
0

Sé que esto es los puntos de mayor edad, pero 2 a tener en cuenta a partir de hoy en Matt codornices respuesta.

Punto 1

Esta

List<Cat> cats = Collections.checkedList(Cat.class, q.list());

En caso de ser esto

List<Cat> cats = Collections.checkedList(q.list(), Cat.class);

El punto 2

De esto

List list = q.list();

a esto

List<T> list = q.list();

reduciría otras advertencias, obviamente, en los marcadores de etiquetas respuesta originales fueron despojados por el navegador.

Respondida el 01/04/2012 a las 23:53
fuente por usuario

votos
5

Al parecer, el método Query.list () de la API de Hibernate no es un tipo seguro "de diseño", y hay planes de cambiar lo .

Creo que la solución más sencilla para evitar las advertencias del compilador es de hecho añadir @SuppressWarnings ( "sin control"). Esta anotación puede ser colocado en el nivel de método o, si dentro de un método, justo antes de una declaración de variables.

En caso de tener un método que encapsula Query.list () y devuelve la lista (o colección), también recibirá una advertencia. Pero éste se suprime el uso de @SuppressWarnings ( "rawtypes").

El método listAndCast (consulta) propuesto por Matt codorniz es menos flexible que Query.list (). Mientras que puedo hacer:

Query q = sess.createQuery("from Cat cat");
ArrayList cats = q.list();

Si intento el código de abajo:

Query q = sess.createQuery("from Cat cat");
ArrayList<Cat> cats = MyHibernateUtils.listAndCast(q);

Voy a buscar un error de compilación: No coinciden los tipos: no se puede convertir de la lista de ArrayList

Respondida el 05/12/2012 a las 18:46
fuente por usuario

votos
-1

Prueba esto:

Query q = sess.createQuery("from Cat cat");
List<?> results = q.list();
for (Object obj : results) {
    Cat cat = (Cat) obj;
}
Respondida el 15/07/2014 a las 22:53
fuente por usuario

votos
16

Se ha pasado mucho tiempo desde que se hizo la pregunta, pero espero que mi respuesta podría ser útil para alguien como yo.

Si se echa un vistazo a javax.persistence API Docs , se verá que algunos de los nuevos métodos se han añadido desde allí Java Persistence 2.0. Uno de ellos es createQuery(String, Class<T>)que vuelve TypedQuery<T>. Se puede utilizar TypedQuerydel mismo modo que lo hizo con Queryesa pequeña diferencia que todas las operaciones son seguras tipo ahora.

Por lo tanto, basta con cambiar su código para smth como esto:

Query q = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q.list();

Y ya está todo.

Respondida el 15/05/2015 a las 20:24
fuente por usuario