Comment comptons-nous les lignes en utilisant les anciennes versions d'Hibernate (~ 2009)?


242

Par exemple, si nous avons une table Livres, comment compterions-nous le nombre total d'enregistrements de livres avec mise en veille prolongée?

Réponses:


310

Pour les anciennes versions d'Hibernate (<5.2):

En supposant que le nom de la classe est Book:

return (Number) session.createCriteria("Book")
                  .setProjection(Projections.rowCount())
                  .uniqueResult();

C'est au moins un Number, très probablement un Long.


10
Il revient longtemps.
dj_segfault

10
Comme @Salandur le suggère, "c'est au moins un nombre", et le type de numéro a les méthodes "intValue ()", "longValue ()", afin que nous puissions facilement obtenir le type primitif souhaité que nous voulons: ((Number) criteria.uniqueResult ()). intValue ()
Jerry Tian

5
Si le mappage d'entité ne peut pas être trouvé à l'aide d'un paramètre de chaîne pour la méthode de création de critères, session.createCriteria (Book.class) peut également être utilisé
Tobias M

5
Comme @MontyBongo l'a dit, j'ai dû me référer à la classe comme ceci: return (Number) session.createCriteria(Book.class).setProjection(Projections.rowCount()).uniqueResult();
bcmoney

2
Ensuite, vous ne devez pas utiliser une base de données rationnelle;). La valeur maximale de long est 9,223372037 × 10¹⁸, qui est laaaaaaaaaarge
Salandur

102

En Java, je dois généralement retourner int et utiliser ce formulaire:

int count = ((Long)getSession().createQuery("select count(*) from Book").uniqueResult()).intValue();

1
La réponse acceptée pour cette question n'a pas fonctionné pour moi, mais la vôtre l'a fait. Merci!
Jason Nichols

est-ce le moyen le plus rapide et le moins cher pour compter une requête? je veux dire en veille prolongée
kommradHomer

57
Quel est l'intérêt d'utiliser un ORM si nous finissons quand même par coder SQL?
thermz

C'est ma principale préoccupation (utiliser SQL au lieu de HQL). Je dois utiliser SELECT imbriqué juste pour compter le nombre de lignes qui viennent après la jointure externe gauche (je n'ai pas trouvé l'implémentation correcte de la jointure externe gauche en hibernation).
Pramod

15
Tout d'abord, cette solution n'utilise pas SQL, c'est HQL. Et l'utilisation de count (*) au lieu de 'select count (e) from E e' ou de critères fonctionne avec @EmbeddedId et les bases de données qui ne prennent pas en charge le nombre de tuple (par exemple. MySQL, où des requêtes comme 'select count ((a, b) ) de table1 'ne fonctionne pas).
BrunoJCM

43

Voici ce que les documents officiels d'hibernation nous disent à ce sujet:

Vous pouvez compter le nombre de résultats de requête sans les renvoyer:

( (Integer) session.createQuery("select count(*) from ....").iterate().next() ).intValue()

Cependant, il ne retourne pas toujours l' Integerinstance, il est donc préférable de l'utiliser java.lang.Numberpour des raisons de sécurité.


1
+1 pour une réponse qui donne la méthode recommandée à l'équipe Hibernate.
Tom

3
Pour moi, cela a donné "java.lang.ClassCastException: java.lang.Long ne peut pas être casté en java.lang.Integer" mais le casting sur un long fonctionne à la place ...
rogerdpack

2
@rogerdpack c'est parce qu'Hibernate a changé le type retourné dans 3.5 en Long: community.jboss.org/wiki/HibernateCoreMigrationGuide35
machines

1
Le type de retour de la fonction count peut être trouvé dans org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions.CountFunction( StandardBasicTypes.LONG )
Guillaume Husta

12

Tu pourrais essayer count(*)

Integer count = (Integer) session.createQuery("select count(*) from Books").uniqueResult();

Booksest le nom de la class- pas la table dans la base de données.


désolé mais cela ne fonctionne pas avec Java et Hibernate :( (j'ai remplacé int par Integer, car il est en Java pour le casting de type.)
artisan

Cela devrait fonctionner - avec Integer au lieu de int? Vous devez mettre le nom de la classe dans le HQL, pas le nom de la table - c'est la seule chose que je puisse penser qui peut être erronée
Jon Spokes

1
Je pense que le post juste en dessous est plus conforme aux principes de base d'Hibernate.
Matt Sidesinger

pour moi, ça ne fonctionne pas avec java et hibernate. que faire à la place?
rParvathi

6

Si vous utilisez Hibernate 5+, la requête sera modifiée comme

Long count = session.createQuery("select count(1) from  Book")
                    .getSingleResult();

Ou si vous avez besoin de TypedQuery

Long count = session.createQuery("select count(1) from  Book",Long.class)
                        .getSingleResult();

6
Long count = (Long) session.createQuery("select count(*) from  Book").uniqueResult();

Il doit s'agir de `` Long count = (Long) session.createQuery ("select count (1) from Book"). UniqueResult (); `` `il améliorera les performances
rajadilipkolli

1

Cela fonctionne dans Hibernate 4 (testé).

String hql="select count(*) from  Book";
Query query= getCurrentSession().createQuery(hql);
Long count=(Long) query.uniqueResult();
return count;

Où getCurrentSession () est:

@Autowired
private SessionFactory sessionFactory;


private Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}

1

C'est très simple, il suffit d'exécuter la requête JPQL suivante:

int count = (
(Number)
    entityManager
    .createQuery(
        "select count(b) " +
        "from Book b")
    .getSingleResult()
).intValue();

La raison pour laquelle nous effectuons la conversion Numberest que certaines bases de données reviendront Longtandis que d'autres reviendront BigInteger, donc pour des raisons de portabilité, vous feriez mieux de convertir en un Numberet d'obtenir un intou un long, selon le nombre de lignes que vous attendez.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.