Comment éviter les avertissements de sécurité de type avec les résultats Hibernate HQL?

Par exemple, j’ai une telle requête:

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

Si j’essaie de faire quelque chose comme ça, il affichera un avertissement “Type safety: L’expression de type List nécessite une conversion non vérifiée pour se conformer à List”:

 List cats = q.list(); 

Est-il possible de l’éviter?

L’utilisation de @SuppressWarnings partout, comme suggéré, est un bon moyen de le faire, même si cela nécessite un peu de saisie à chaque fois que vous appelez q.list() .

Il y a trois autres techniques que je suggérerais:

Collections.checkedList()

Remplacez votre affectation par ceci:

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

Vous pourriez vouloir vérifier le javadoc pour cette méthode , en particulier en ce qui concerne les equals et hashCode .

Ecrivez un assistant

Il suffit de refactoriser tous vos @SuppressWarnings en un seul endroit:

 List cats = MyHibernateUtils.listAndCast(q); ... public static  List listAndCast(Query q) { @SuppressWarnings("unchecked") List list = q.list(); return list; } 

Empêcher Eclipse de générer des avertissements pour les problèmes inévitables

Dans Eclipse, accédez à Fenêtre> Préférences> Java> Compilateur> Erreurs / Avertissements et sous Type générique, cochez la case Ignore unavoidable generic type problems due to raw APIs

Cela désactivera les avertissements inutiles pour des problèmes similaires, comme celui décrit ci-dessus, qui sont inévitables.

Certains commentaires:

  • J’ai choisi de passer la Query au lieu du résultat de q.list() car cette méthode de «sortingche» ne peut être utilisée que pour tromper avec Hibernate et non pour tromper une List en général.
  • Vous pouvez append des méthodes similaires pour .iterate() etc.

Nous utilisons aussi @SuppressWarnings("unchecked") , mais nous essayons le plus souvent de ne l’utiliser que sur la déclaration de la variable, pas sur la méthode dans son ensemble:

 public List findAll() { Query q = sess.createQuery("from Cat cat"); @SuppressWarnings("unchecked") List cats = q.list(); return cats; } 

Il y a longtemps que la question a été posée, mais j’espère que ma réponse pourrait être utile à quelqu’un comme moi.

Si vous jetez un coup d’œil aux documents d’ api javax.persistence, vous verrez que de nouvelles méthodes ont été ajoutées depuis Java Persistence 2.0 . L’un d’eux est createQuery(Ssortingng, Class) qui renvoie TypedQuery . Vous pouvez utiliser TypedQuery comme vous l’avez fait avec Query avec cette petite différence que toutes les opérations sont maintenant de type sécurisé.

Alors, changez simplement votre code en smth comme ceci:

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

Et vous êtes tous ensemble.

Essayez d’utiliser TypedQuery au lieu de Query . Par exemple au lieu de cela: –

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

Utilisez ceci:-

 TypedQuery q1 = sess.createQuery("from Cat cat", Cat.class); List cats = q1.list(); 

Dans notre code, nous annotons les méthodes d’appel avec:

@SuppressWarnings (“non vérifié”)

Je sais que cela semble être un hack, mais un co-développeur a vérifié récemment et a trouvé que c’était tout ce que nous pouvions faire.

Apparemment, la méthode Query.list () de l’API Hibernate n’est pas de type “par conception”, et il n’est pas prévu de la modifier .

Je pense que la solution la plus simple pour éviter les avertissements du compilateur est d’append @SuppressWarnings (“non vérifié”). Cette annotation peut être placée au niveau de la méthode ou, si dans une méthode, juste avant une déclaration de variable.

Si vous avez une méthode qui encapsule Query.list () et renvoie List (ou Collection), vous obtenez également un avertissement. Mais celui-ci est supprimé en utilisant @SuppressWarnings (“rawtypes”).

La méthode listAndCast (Query) proposée par Matt Quail est moins flexible que Query.list (). Bien que je puisse faire:

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

Si j’essaye le code ci-dessous:

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

Je vais obtenir une erreur de compilation: Incompatibilité de type: impossible de convertir de la liste en ArrayList

Ce n’est pas un oubli ou une erreur. L’avertissement reflète un véritable problème sous-jacent – le compilateur Java ne peut en aucun cas être vraiment sûr que la classe hibernate va faire son travail correctement et que la liste renvoyée contiendra uniquement des chats. Toutes les suggestions ici sont bien.

Non, mais vous pouvez l’isoler dans des méthodes de requête spécifiques et supprimer les avertissements avec une @SuppressWarnings("unchecked") .

Nous avons eu le même problème. Mais ce n’était pas un gros problème pour nous car nous devions résoudre d’autres problèmes plus importants avec Hibernate Query and Session.

Plus précisément:

  1. contrôler quand une transaction pourrait être engagée. (Nous voulions compter le nombre de fois où un tx était “démarré” et ne le validait que lorsque le tx était “terminé” le même nombre de fois qu’il était démarré. Utile pour le code qui ne sait pas s’il doit démarrer une transaction. tout code nécessitant un tx ne fait que “démarrer” un fichier et le termine une fois terminé.)
  2. Collecte de mésortingques de performance
  3. Retarder le démarrage de la transaction jusqu’à ce que l’on sache que quelque chose sera effectivement fait.
  4. Comportement plus doux pour query.uniqueResult ()

Donc pour nous, nous avons:

  1. Créer une interface (AmplafiQuery) qui étend la requête
  2. Créez une classe (AmplafiQueryImpl) qui étend AmplafiQuery et encapsule un org.hibernate.Query
  3. Créez un gestionnaire Txman qui renvoie un Tx.
  4. Tx a les différentes méthodes createQuery et renvoie AmplafiQueryImpl

Et enfin,

AmplafiQuery a un “asList ()” qui est une version générique de Query.list () AmplafiQuery a un “unique ()” qui est une version générique de Query.uniqueResult () (et enregistre simplement un problème plutôt que de lancer un exception)

C’est beaucoup de travail pour éviter @SuppressWarnings. Cependant, comme je l’ai dit (et répertorié), il y en a beaucoup d’autres mieux! raisons de faire le travail d’emballage.

Les nouvelles versions de Hibernate prennent désormais en charge un object de type Query sûr de sorte que vous ne devez plus utiliser @SuppressWarnings ou implémenter un hack pour que les avertissements du compilateur disparaissent. Dans l’ API de session , Session.createQuery désormais un object de type sécurisée Query . Vous pouvez l’utiliser de cette façon:

 Query query = session.createQuery("FROM Cat", Cat.class); List cats = query.list(); 

Vous pouvez également l’utiliser lorsque le résultat de la requête ne renvoie pas un chat:

 public Integer count() { Query query = sessionFactory.getCurrentSession().createQuery("SELECT COUNT(id) FROM Cat", Integer.class); return query.getSingleResult(); } 

Ou lorsque vous effectuez une sélection partielle:

 public List Ssortingng getName() { Query query = sessionFactory.getCurrentSession().createQuery("SELECT id, name FROM Cat", Object[].class); return query.list(); } 

La solution de Joe Dean semble intéressante, mais pensez-vous que cela en vaut la peine – créez une nouvelle liste et parcourez tous les éléments pour vous débarrasser des avertissements?

(désolé, ne peut pas append un commentaire directement à sa solution pour une raison quelconque)

Je sais que c’est plus vieux mais 2 points à noter dès aujourd’hui dans la réponse de Matt Quails.

Point 1

Ce

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

Devrait être ça

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

Point 2

De ceci

 List list = q.list(); 

pour ça

 List list = q.list(); 

réduirait évidemment d’autres avertissements dans les repères de repères d’origine ont été supprimés par le navigateur.

Essaye ça:

 Query q = sess.createQuery("from Cat cat"); List results = q.list(); for (Object obj : results) { Cat cat = (Cat) obj; } 

Une bonne solution pour éviter les avertissements de sécurité de type avec une requête d’hibernation consiste à utiliser un outil tel que TorpedoQuery pour vous aider à créer un hql de type sécurisé.

 Cat cat = from(Cat.class); org.torpedoquery.jpa.Query select = select(cat); List cats = select.list(entityManager); 

Si vous ne souhaitez pas utiliser @SuppressWarnings (“non vérifié”), vous pouvez effectuer les opérations suivantes.

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

FYI – J’ai créé une méthode util qui fait cela pour moi, donc je ne jette pas de code sur mon code et je n’ai pas besoin d’utiliser @SupressWarning.