J'ai une insertOrUpdate
méthode qui insère un Entity
quand il n'existe pas ou le met à jour s'il existe. Pour activer cela, je dois findByIdAndForeignKey
, s'il retourne null
insérer sinon, mettre à jour. Le problème est de savoir comment vérifier s'il existe? Alors j'ai essayé getSingleResult
. Mais cela lève une exception si le
public Profile findByUserNameAndPropertyName(String userName, String propertyName) {
String namedQuery = Profile.class.getSimpleName() + ".findByUserNameAndPropertyName";
Query query = entityManager.createNamedQuery(namedQuery);
query.setParameter("name", userName);
query.setParameter("propName", propertyName);
Object result = query.getSingleResult();
if (result == null) return null;
return (Profile) result;
}
mais getSingleResult
jette un Exception
.
Merci
getSingleResult()
est utilisé dans des situations comme: " Je suis tout à fait sûr que ce disque existe. Tirez-moi si ce n'est pas le cas ". Je ne veux pas testernull
chaque fois que j'utilise cette méthode car je suis sûr qu'elle ne la retournera pas. Sinon, cela entraîne beaucoup de programmation passe-partout et défensive. Et si le disque n'existe vraiment pas (contrairement à ce que nous avons supposé), il vaut bien mieux l'avoirNoResultException
par rapport àNullPointerException
quelques lignes plus tard. Bien sûr, avoir deux versions degetSingleResult()
serait génial, mais si je devais en choisir une ...J'ai encapsulé la logique dans la méthode d'aide suivante.
la source
Essayez ceci dans Java 8:
la source
.orElse(null)
Voici une bonne option pour faire cela:
la source
TypedQuery<T>
cependant, auquel cas legetResultList()
est alors déjà correctement tapé comme unList<T>
.fetch()
l'entité peut ne pas être complètement peuplée. Voir stackoverflow.com/a/39235828/661414setMaxResults()
a une interface fluide pour que vous puissiez écrirequery.setMaxResults(1).getResultList().stream().findFirst().orElse(null)
. Cela devrait être le schéma d'appel le plus efficace de Java 8+.Spring a une méthode utilitaire pour cela:
la source
J'ai fait (en Java 8):
la source
À partir de JPA 2.2 , au lieu de
.getResultList()
vérifier si la liste est vide ou de créer un flux, vous pouvez renvoyer le flux et prendre le premier élément.la source
Si vous souhaitez utiliser le mécanisme try / catch pour gérer ce problème .. alors il peut être utilisé pour agir comme if / else. J'ai utilisé le try / catch pour ajouter un nouvel enregistrement alors que je n'en trouvais pas un existant.
la source
Voici une version typée / générique, basée sur l'implémentation de Rodrigo IronMan:
la source
Il existe une alternative que je recommanderais:
Cette sauvegarde contre l'exception de pointeur nul, garantit qu'un seul résultat est renvoyé.
la source
Alors ne fais pas ça!
Vous avez deux options:
Exécutez une sélection pour obtenir le COUNT de votre jeu de résultats et n'extrayez les données que si ce nombre est différent de zéro; ou
Utilisez l'autre type de requête (qui obtient un jeu de résultats) et vérifiez si elle a 0 ou plusieurs résultats. Il devrait en avoir 1, alors retirez-le de votre collection de résultats et vous avez terminé.
J'irais avec la deuxième suggestion, en accord avec Cletus. Il donne de meilleures performances que (potentiellement) 2 requêtes. Moins de travail aussi.
la source
En combinant les bits utiles des réponses existantes (limiter le nombre de résultats, vérifier que le résultat est unique) et en utilisant le nom de la méthode estabilshed (Hibernate), on obtient:
la source
La méthode non documentée
uniqueResultOptional
dans org.hibernate.query.Query devrait faire l'affaire. Au lieu d'avoir à attraper un,NoResultException
vous pouvez simplement appelerquery.uniqueResultOptional().orElse(null)
.la source
J'ai résolu ce problème en utilisant
List<?> myList = query.getResultList();
et en vérifiant simyList.size()
égal à zéro.la source
Voici la même logique que d'autres suggérées (obtenir le resultList, renvoyer son seul élément ou null), en utilisant Google Guava et un TypedQuery.
Notez que Guava renverra l'exception IllegalArgumentException peu intuitive si le jeu de résultats a plus d'un résultat. (L'exception a du sens pour les clients de getOnlyElement (), car elle prend la liste de résultats comme argument, mais est moins compréhensible pour les clients de getSingleResultOrNull ().)
la source
Voici une autre extension, cette fois dans Scala.
Avec ce souteneur:
la source
Regardez ce code:
return query.getResultList().stream().findFirst().orElse(null);
Quand
findFirst()
est appelé peut-être peut-être lancé une NullPointerException.la meilleure approche est:
return query.getResultList().stream().filter(Objects::nonNull).findFirst().orElse(null);
la source
Donc, toute la solution «essayez de réécrire sans exception» dans cette page a un problème mineur. Soit il ne lance pas d'exception NonUnique, ni ne le lance également dans certains cas erronés (voir ci-dessous).
Je pense que la bonne solution est (peut-être) celle-ci:
Son retour avec null s'il y a 0 élément dans la liste, retourne non unique s'il y a différents éléments dans la liste, mais ne retourne pas non-unique quand l'un de vos sélections n'est pas correctement conçu et retourne le même objet plus d'une fois.
N'hésitez pas à commenter.
la source
J'ai réalisé cela en obtenant une liste de résultats puis en vérifiant si elle est vide
C'est tellement ennuyeux qui
getSingleResult()
jette des exceptionsJette:
la source
Cela fonctionne pour moi:
la source