2008-10-21 5 views
23

Supposons que les objets de type A soient stockés dans la base de données. Voici la façon dont je charge un spécifique de DB en utilisant Mise en veille prolongée:Hibernation: vérifier si l'objet existe

org.hibernate.Session session = ...; 
long id = 1; 
A obj = session.load(A.class, id); 

Si l'objet avec id = 1 n'existe pas que je vais me ObjectNotFoundException. Mais existe-t-il un moyen de vérifier si un tel objet existe sans avoir à intercepter l'exception? Ce que je voudrais avoir est lissée comme:

org.hibernate.Session session = ...; 
long id = 1; 
boolean exists = session.exists(A.class, id); 
if(exists){ 
// do smth..... 
} 

Impossible de trouver hibernent docs ...

Répondre

24

Vous pouvez utiliser session.get:

public Object get(Class clazz, 
        Serializable id) 
      throws HibernateException 

Il renvoie null si l'objet n'existe pas dans la base de données. Vous pouvez trouver plus d'informations dans Hibernate API Documentation.

+0

Hmm ... Je reçois toujours la même chose (ObjectNotFoundException), peu importe si je utilisez "charger" ou "obtenir". –

+0

Peut-être que vous obtenez une exception d'un session.load() précédent? De la documentation pour ObjectNotFoundException: Cette exception ne peut pas être levée lorsque load() est appelée car load() renvoie un proxy si possible Utilisez Session.get() pour tester si une ligne existe dans la base de données. – Juanma

+2

obtenir des travaux mais c'est une approche lente puisque Hibernate devra aller chercher toutes les colonnes et les affecter au nouvel objet et le stocker dans la session. Si vous ne voulez pas gaspiller inutilement des ressources, pensez plutôt à l'approche HQL. –

42

vous pouvez utiliser HQL pour vérifier l'existence d'objets:

public Boolean exists (DTOAny instance) { 
    Query query = getSession().    
    createQuery("select 1 from DTOAny t where t.key = :key"); 
     query.setString("key", instance.getKey()); 
    return (query.uniqueResult() != null); 
} 

uniqueResult et hiberne() méthode renvoie NULL si aucune donnée n'a été trouvée. En utilisant HQL, vous pouvez créer des critères de requête plus complexes.

10

Mise en veille prolongée

Récupère touche uniquement pour des performances optimales:

public boolean exists(Class clazz, String idKey, Object idValue) { 
    return getSession().createCriteria(clazz) 
      .add(Restrictions.eq(idKey, idValue)) 
      .setProjection(Projections.property(idKey)) 
      .uniqueResult() != null; 
} 

JPA

Puisqu'Hibernate est une implémentation de JPA, il est possible de inject un EntityManager. Cette méthode a également de bonnes performances car il lazily fetches l'instance:

public boolean exists(Class clazz, Object key) { 
    try { 
     return entitymanager.getReference(Entity.class, key) != null; 
    } catch (EntityNotFoundException.class) { 
     return false; 
    } 
} 
+2

Vous n'avez pas besoin d'une condition pour la dernière ligne: Vous pouvez utiliser .uniqueResult()! = Null; – stephenwebber

+1

Thx pour l'indice, j'ai mis à jour le code! – Journeycorner

3

Un peu de méthode simplifiée @Journeycorner

public boolean exists(Class<?> clazz, Object idValue) { 
    return getSession().createCriteria(clazz) 
      .add(Restrictions.idEq(idValue)) 
      .setProjection(Projections.id()) 
      .uniqueResult() != null; 
} 

A ci-dessous méthode peut être utile aussi. Gardez à l'esprit que cette méthode peut être utilisée qu'avec les critères qui peuvent produire pas plus d'un enregistrement (comme Restrictions.idEq() critères)

public static boolean uniqueExists(Criteria uniqueCriteria) { 
    uniqueCriteria.setProjection(Projections.id()); 
    return uniqueCriteria.uniqueResult() != null; 
} 
Questions connexes