Как мы подсчитываем строки, используя более старые версии Hibernate (~ 2009)?

242

Например, если у нас есть таблица Books, как бы мы посчитали общее количество записей книги в режиме гибернации?

ремесленник
источник

Ответы:

310

Для более старых версий Hibernate (<5.2):

Предполагая, что имя класса - Book:

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

Это как минимум a Number, скорее всего a Long.

Salandur
источник
10
Возвращается долго.
dj_segfault
10
Как подсказывает @Salandur, «Это по крайней мере число», а тип Number имеет методы «intValue ()», «longValue ()», поэтому мы можем легко получить желаемый тип примитива, который нам нужен: ((Number) attribute.uniqueResult) ()). intValue ()
Джерри Тян
5
Если сопоставление сущностей невозможно найти с помощью строкового параметра в методе создания критериев, также можно использовать session.createCriteria (Book.class)
Тобиас М
5
Как сказал @MontyBongo, мне действительно нужно было сослаться на класс следующим образом: return (Number) session.createCriteria(Book.class).setProjection(Projections.rowCount()).uniqueResult();
bcmoney
2
Тогда не стоит использовать рациональную базу данных;). Максимальное значение long составляет 9,223372037 × 10¹⁸, то есть laaaaaaaaaarge
Salandur
102

В Java мне обычно нужно вернуть int и использовать эту форму:

int count = ((Long)getSession().createQuery("select count(*) from Book").uniqueResult()).intValue();
marioosh
источник
1
Принятый ответ на этот вопрос не сработал для меня, но ваш сработал. Спасибо!
Джейсон Николс
Это самый быстрый и дешевый способ подсчета запросов? я имею в виду спящий - мудрый
kommradHomer
57
Какой смысл использовать ORM, если мы все равно будем кодировать SQL?
thermz
Это моя главная проблема (использование SQL вместо HQL). Я должен использовать вложенный SELECT только для подсчета количества строк, которые идут после левого внешнего соединения (я не нашел правильной реализации левого внешнего соединения в спящем режиме).
Прамод
15
Во-первых, это решение не использует SQL, это HQL. И использование count (*) вместо «select count (e) from E e» или критериев работает с @EmbeddedId и базами данных, которые не поддерживают подсчет кортежей (например, MySQL, где запросы типа «select count» ((a, b) ) из таблицы 1 'не работает).
BrunoJCM
43

Вот что официальные документы по гибернации говорят нам об этом:

Вы можете посчитать количество результатов запроса, не возвращая их:

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

Однако он не всегда возвращает Integerэкземпляр, поэтому его лучше использовать java.lang.Numberдля безопасности.

Антонио
источник
1
+1 за ответ, который дает рекомендуемый метод для команды Hibernate.
Том
3
Для меня это дало "java.lang.ClassCastException: java.lang.Long не может быть приведен к java.lang.Integer", но вместо этого работает приведение к Long ...
rogerdpack
2
@rogerdpack это потому, что Hibernate изменил возвращаемый тип в 3.5 на Long: community.jboss.org/wiki/HibernateCoreMigrationGuide35
механизм
1
Тип возврата для функции count можно найти в org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions.CountFunction( StandardBasicTypes.LONG )
Гийом Хуста,
12

Вы могли бы попробовать count(*)

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

Где Booksимя от class- не таблица в базе данных.

Джон Спокс
источник
извините, но он не работает с Java и Hibernate :( (я заменил int на Integer, как это было в Java для приведения типов.)
craftman
Должно работать - с Integer вместо int? Вам нужно поместить имя класса в HQL, а не имя таблицы - это единственное, что я могу подумать, что это может быть неправильно
Джон Спокс
1
Я полагаю, что публикация непосредственно под этим больше соответствует основным принципам Hibernate.
Мэтт Сидесингер
для меня это не работает с Java и Hibernate. что делать вместо этого?
rParvathi
6

Если вы используете Hibernate 5+, запрос будет изменен как

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

Или если вам нужен TypedQuery

Long count = session.createQuery("select count(1) from  Book",Long.class)
                        .getSingleResult();
rajadilipkolli
источник
6
Long count = (Long) session.createQuery("select count(*) from  Book").uniqueResult();
xrcwrn
источник
Это должно быть``` Long count = (Long) session.createQuery ("select count (1) from Book"). UniqueResult (); `` `это улучшит производительность
rajadilipkolli
1

Это работает в Hibernate 4 (проверено).

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

Где getCurrentSession ():

@Autowired
private SessionFactory sessionFactory;


private Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
LucianoDemuru
источник
1

Это очень просто, просто запустите следующий запрос JPQL:

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

Причина, по которой мы приводим данные, Numberзаключается в том, что некоторые базы данных возвращаются, Longа другие - возвращаются BigInteger, поэтому для удобства переноса вам лучше привести к типу a Numberи получить a intили a long, в зависимости от того, сколько строк вы ожидаете подсчитать.

Влад Михалча
источник