Comment vérifier si un enregistrement existe en utilisant JPA

je veux savoir si un enregistrement donné est présent dans une base de données ou non. jusqu'à présent j'ai réalisé ceci en écrivant une requête JPA et en l'exécutant par getSingleResult() méthode. ce serait jeter un NoResultException si l'enregistrement avec le paramètre n'existe pas. Bien sûr, ce n'est pas un must pour le disque d'exister, donc c'est le comportement normal parfois, c'est pourquoi je me suis demandé, est-il nécessaire de jeter une Exception que je dois gérer par un bloc d'attrape? Autant que je sache, le coût de l'Exception la manipulation est assez grande, donc je ne suis pas très satisfait de cette solution, aussi, je n'ai même pas besoin de l'objet, j'ai seulement besoin de savoir son existence dans le DB.

Est-il une meilleure façon de vérifier si un objet existe ou pas? par exemple. en utilisant getResultList() et la vérification de sa taille peut-être?

21
demandé sur Yi Jiang 2010-12-07 11:35:55

5 réponses

Si vous voulez simplement savoir si l'objet existe, envoyer un SELECT COUNT à votre base de données. Ça fera 0 ou 1.

le coût de la manipulation de l'exception n'est pas si élevé (à moins que vous ne fassiez cela des millions de fois pendant une opération normale), donc je ne m'embêterais pas.

Mais le code ne reflète pas vraiment votre intention. Depuis getSingleResult() appelle getResultList() en interne, c'est plus clair comme ça:

public boolean objExists(...) {
    return getResultList(...).size() == 1;
}

si vous interrogez par l'id de l'objet et que vous avez activé la mise en cache, cela deviendra une simple recherche dans le cache si l'objet a déjà été chargé.

22
répondu Aaron Digulla 2010-12-07 08:41:07

essayez d'éviter de charger l'entity dans la session (getSingleResult()) juste pour vérifier son existence. Un comptage est mieux ici. Avec L'API de requête de critères, cela ressemblerait à ceci:

public <E extends AbstractEntity> boolean exists(final Class<E> entityClass, final int id) {
    final EntityManager em = getEntityManager();
    final CriteriaBuilder cb = em.getCriteriaBuilder();

    final CriteriaQuery<Long> cq = cb.createQuery(Long.class);
    final Root<E> from = cq.from(entityClass);

    cq.select(cb.count(from));
    cq.where(cb.equal(from.get(AbstractEntity_.id), id));

    final TypedQuery<Long> tq = em.createQuery(cq);
    return tq.getSingleResult() > 0;
}
15
répondu Radu 2016-05-23 10:25:30

si vous recherchez par clé primaire, vous pouvez aussi utiliser Entitymanger.find(entityClass, primaryKey) qui renvoie null lorsque l'entité n'existe pas.

5
répondu Jörn Horstmann 2010-12-07 08:46:25

il suffit d'utiliser count(e) dans votre requête, donc pas de NoResultException sera lancé et vous éviterez de charger l'objet entity

Ainsi, le code Java peut être comme suit:

public boolean isRecordExist() {
    String query = "select count(e) from YOUR_ENTITY e where ....";
    // you will always get a single result
    Long count = (Long) entityManager.createQuery( query ).getSingleResult();
    return ( ( count.equals( 0L ) ) ? false : true );
}

j'Espère que l'aide à quelqu'un :)

5
répondu Halayem Anis 2017-08-30 10:27:07

voici une approche générique pour travailler avec un type et arbitraire ID valeur

public boolean exists(Object key) { 
    EntityManager entityManager = getEntityManager();
    Metamodel metamodel = entityManager.getMetamodel();
    EntityType<T> entity = metamodel.entity(entityClass);
    SingularAttribute<T, ? extends Object> declaredId = entity.getDeclaredId(key.getClass());
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    javax.persistence.criteria.CriteriaQuery<T> cq = cb.createQuery(entityClass);
    Root<T> from = cq.from(entityClass);
    Predicate condition = cb.equal(from.get(declaredId), key);
    cq.where(condition);
    TypedQuery<T> q = entityManager.createQuery(cq);
    return q.getResultList().size() > 0; 
}
1
répondu user738048 2017-12-13 23:28:07