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?

artisan
la source

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.

Salandur
la source
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();
marioosh
la source
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é.

Antonio
la source
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.

Jon Spokes
la source
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();
rajadilipkolli
la source
6
Long count = (Long) session.createQuery("select count(*) from  Book").uniqueResult();
xrcwrn
la source
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();
}
LucianoDemuru
la source
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.

Vlad Mihalcea
la source