Par exemple, j'ai une telle requête:
Query q = sess.createQuery("from Cat cat");
List cats = q.list();
Si j'essaye de faire quelque chose comme ça, il montre l'avertissement suivant
Type safety: The expression of type List needs unchecked conversion to conform to List<Cat>
List<Cat> cats = q.list();
Existe-t-il un moyen de l'éviter?
L'utilisation de @SuppressWarnings
Partout, comme suggéré, est une bonne façon de le faire, même si cela implique un peu de frappe à chaque fois que vous appelez q.list()
.
Il y a deux autres techniques que je suggérerais:
Écrivez un assistant de casting
Refactorisez simplement tous vos @SuppressWarnings
En un seul endroit:
List<Cat> cats = MyHibernateUtils.listAndCast(q);
...
public static <T> List<T> listAndCast(Query q) {
@SuppressWarnings("unchecked")
List list = q.list();
return list;
}
Empêche Eclipse de générer des avertissements pour des 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:
Query
au lieu du résultat de q.list()
parce que de cette façon cette méthode de "tricherie" ne peut être utilisée que pour tricher avec Hibernate, et non pour tricher tout List
en général..iterate()
etc.Cela fait longtemps que la question n'a pas été posée, mais j'espère que ma réponse pourra être utile à quelqu'un comme moi.
Si vous jetez un œil à javax.persistence api docs , vous verrez que de nouvelles méthodes y ont été ajoutées depuis Java Persistence 2.0
. L'un d'eux est createQuery(String, Class<T>)
qui renvoie TypedQuery<T>
. Vous pouvez utiliser TypedQuery
comme vous l'avez fait avec Query
avec cette petite différence que toutes les opérations sont désormais sécurisées.
Donc, changez simplement votre code en smth comme ceci:
Query q = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q.list();
Et vous êtes prêt.
Nous utilisons également @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<Cat> findAll() {
Query q = sess.createQuery("from Cat cat");
@SuppressWarnings("unchecked")
List<Cat> cats = q.list();
return cats;
}
Essayez d'utiliser TypedQuery
au lieu de Query
. Par exemple au lieu de cela: -
Query q = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q.list();
Utilisez ceci:-
TypedQuery<Cat> q1 = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q1.list();
Dans notre code, nous annotons les méthodes d'appel avec:
@SuppressWarnings ("non coché")
Je sais que cela ressemble à un hack, mais un co-développeur a vérifié récemment et a découvert que c'était tout ce que nous pouvions faire.
Apparemment, la méthode Query.list () dans l'API Hibernate n'est pas sécurisée de type "par conception", et il y a pas de plans pour la changer .
Je crois que la solution la plus simple pour éviter les avertissements du compilateur est en effet d'ajouter @SuppressWarnings ("non coché"). Cette l'annotation peut être placée au niveau de la méthode ou, si à l'intérieur d'une méthode, juste avant une déclaration de variable.
Dans le cas où vous avez une méthode qui encapsule Query.list () et renvoie List (ou Collection), vous obtenez également un avertissement. Mais celui-ci est supprimé à l'aide de @SuppressWarnings ("rawtypes").
La méthode listAndCast (Query) proposée par Matt Quail est moins flexible que Query.list (). Alors que je peux 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<Cat> cats = MyHibernateUtils.listAndCast(q);
Je vais obtenir une erreur de compilation: Non-concordance de type: impossible de convertir de List en ArrayList
Ce n'est pas un oubli ou une erreur. L'avertissement reflète un véritable problème sous-jacent - il n'y a aucun moyen que le compilateur Java puisse vraiment être sûr que la classe hibernate fera son travail correctement et que la liste qu'elle renvoie ne contiendra que des chats Toutes les suggestions ici sont très bien.
Non, mais vous pouvez l'isoler dans des méthodes de requête spécifiques et supprimer les avertissements avec une annotation @SuppressWarnings("unchecked")
.
Les nouvelles versions d'Hibernate prennent désormais en charge un type sécurisé Query<T>
objet pour que vous n'ayez plus à utiliser @SuppressWarnings
ou implémentez un hack pour faire disparaître les avertissements du compilateur. Dans API de session , Session.createQuery
renverra maintenant un type sécurisé Query<T>
objet. Vous pouvez l'utiliser de cette façon:
Query<Cat> query = session.createQuery("FROM Cat", Cat.class);
List<Cat> cats = query.list();
Vous pouvez également l'utiliser lorsque le résultat de la requête ne renvoie pas de Cat:
public Integer count() {
Query<Integer> query = sessionFactory.getCurrentSession().createQuery("SELECT COUNT(id) FROM Cat", Integer.class);
return query.getSingleResult();
}
Ou lors d'une sélection partielle:
public List<Object[]> String getName() {
Query<Object[]> query = sessionFactory.getCurrentSession().createQuery("SELECT id, name FROM Cat", Object[].class);
return query.list();
}
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:
Donc pour nous, nous avons:
Et enfin,
AmplafiQuery a un "asList ()" qui est une version générique activée de Query.list () AmplafiQuery a un "unique ()" qui est une version générique activée de Query.uniqueResult () (et enregistre simplement un problème plutôt que de lancer un exception)
C'est beaucoup de travail pour éviter simplement @SuppressWarnings. Cependant, comme je l'ai dit (et énuméré), il y a beaucoup d'autres meilleurs! raisons de faire le travail d'emballage.
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 juste pour vous débarrasser des avertissements?
(désolé, impossible d'ajouter un commentaire directement à sa solution pour une raison quelconque)
Je sais que c'est plus ancien mais 2 points à noter aujourd'hui dans Matt Quails Answer.
Cette
List<Cat> cats = Collections.checkedList(Cat.class, q.list());
Devrait être ceci
List<Cat> cats = Collections.checkedList(q.list(), Cat.class);
De cela
List list = q.list();
pour ça
List<T> list = q.list();
réduirait évidemment les autres avertissements dans les marqueurs de balises de réponse d'origine qui ont été supprimés par le navigateur.