как можно получить количество строк в спящем режиме, когда у hql есть группа?

У меня есть запрос hql, у которого есть группа. В результате разбивки на страницы я хочу получить подсчет всех результатов, отображаемых в разбивке на страницы. В запросе, который не имеет группы по. Я пишу утилиту, которая создает счетчик запросов из запроса hql, подобного этому

select u 
from Personel u 
where u.lastname='azizkhani'

я нахожу основное ключевое слово "from" и подстроку hql и добавляю count (*), а затем делаю этот запрос

select count(*) 
from Personel u  
where u.lastname='azizkhani'

когда у меня есть запрос, содержащий группу, я не могу сделать это так

select u.lastname,count(*) 
from Personel u 
group by u.lastname;

количество этого запроса в sql равно

select count(*) 
   from (
         select u.lastname,count(*) 
         from tbl_personel u 
         group  by u.lastname
    )

как я могу сгенерировать группу по запросу из hql ??

У меня есть GenericRepository, у которого есть такой метод

public <U> PagingResult<U> getAllGrid(String hql,Map<String, Object> params,PagingRequest searchOption);

и разработчик называет это так

   String hqlQuery = " select e from Personel e where 1<>2 and e.lastname=:lastname";

    HashMap<String, Object> params = new HashMap<String, Object>();
    params.put("lastname", 'azizkhani');


    return getAllGrid(hqlQuery, params, new PagingRequest( 0/*page*/, 10 /*size*/) );

в GenericRepository я верну объект PagingResult, у которого есть свойство

public class PagingResult<T> {

    private int totalElements;

    @JsonProperty("rows")
    private List<T> items;

    public PagingResult() {

    }

    public PagingResult(int totalElements, List<T> items) {
        super();
        this.totalElements = totalElements;
        this.items = items;
    }


    public int getTotalElements() {
        return totalElements;
    }

    public void setTotalElements(int totalElements) {
        this.totalElements = totalElements;
    }


    public List<T> getItems() {
        return items;
    }

    public void setItems(List<T> items) {
        this.items = items;
    }

}

В GenericRepository я выполню два запроса, первый для получения результата 10 и второй для получения totalRecords. Разработчик просто отправит Hql. Я сделаю hql для получения totalcount. для запроса, который не имеет "отличных" или "группировать по", я делаю hql. но когда в hql есть "отдельные" и "группировать по", у меня есть проблема.

public <U> PagingResult<U> getAllGrid(String hql, Map<String, Object> params, PagingRequest searchOption) {
        Session session = getSession();
        applyDafaultAuthorizeFilter(session);


        Query query = session.createQuery(hql);
        if (searchOption != null) {
            if (searchOption.getSize() > 0) {
                query.setFirstResult(searchOption.getPage() * searchOption.getSize());
                query.setMaxResults(searchOption.getSize());
            }
        }
        if (params != null)
            HQLUtility.setQueryParameters(query, params);

        List<U> list = query.getResultList();

        Query countQuery = session.createQuery("select count(*) " + HQLUtility.retriveCountQueryFromHql(hql));

        if (params != null)
            HQLUtility.setQueryParameters(countQuery, params);

        int count = ((Long) countQuery.uniqueResult()).intValue();
        if (searchOption != null)
            return new PagingResult<U>(searchOption.getPage(), count, searchOption.getSize(), list);
        else
            return new PagingResult<U>(0, count, 0, list);
    }


   public static StringBuffer retriveCountQueryFromHql(StringBuffer jql) {
        if(jql.indexOf("order by")>=0)
            jql.replace(jql.indexOf("order by"), jql.length(),"");
        String mainQuery = jql.toString();

        jql = new StringBuffer(jql.toString().replace('\t', ' '));
        int firstIndexPBas = jql.indexOf(")");
        int firstIndexPBaz = jql.lastIndexOf("(", firstIndexPBas);
        while (firstIndexPBas > 0) {
            for (int i = firstIndexPBaz; i < firstIndexPBas + 1; i++)
                jql.replace(i, i + 1, "*");
            firstIndexPBas = jql.indexOf(")");
            firstIndexPBaz = jql.lastIndexOf("(", firstIndexPBas);
        }
        int Indexfrom = jql.indexOf(" from ");
        return new StringBuffer(" " + mainQuery.substring(Indexfrom, jql.length()));
    }

    public void applyDafaultAuthorizeFilter(Session session) {
        Filter filter = session.enableFilter("defaultFilter");
        filter.setParameter("userId", SecurityUtility.getAuthenticatedUserId());
        filter.setParameter("orgId", SecurityUtility.getAuthenticatedUserOrganization().getId());
    }

как я могу решить эту проблему без изменения подписи моего GenericRepository ???

Я думаю, у меня есть решение, которое конвертирует hql в sql и создает собственный запрос, подобный этому select count (*) from (hql_to_sql), но у меня две проблемы

  1. hql в дозу sql не имеет api, поддерживающего параметр
  2. hql в дозу sql не имеет API, поддерживающего фильтр гибернации

person ali akbar azizkhani    schedule 13.09.2016    source источник


Ответы (5)


Почему бы не заменить group by на count(distinct)?

Так что вместо

select u from tbl_personel u group by u.lastname

ты сделаешь

select count(distinct u.lastname) from tbl_personel u

person Christian Beikov    schedule 23.03.2017

Я столкнулся с той же проблемой, но мой HQL-оператор имеет несколько столбцов в предложении GROUP-BY:

select u.firstname, u.lastname
from Personel u 
group by u.firstname, u.lastname;

Мне нужно подсчитать полученные строки для разбивки на страницы. Подход Кристиана Бейкова не сработал, потому что я не могу использовать несколько столбцов в одной (отдельной) функции.

Решил проблему с вложенными агрегатными функциями:

select sum(count(distinct u.lastname))
from Personel u 
group by u.firstname, u.lastname;

"u.lastname" должно быть столбцом NOT NULL.

Этот оператор работает в HQL с Oracle-DB.

person Nico Bachmann    schedule 21.09.2017

Если это действительно ваш HQL-запрос, который вам нужно разбить на страницы:

select u.lastname, count(u) 
from Personel u 
group by u.lastname

и вам нужен общий счет для этого запроса, тогда вы можете запускать только SQL-запрос, поскольку Hibernate JPQL не поддерживает производные таблицы.

Итак, просто запустите собственный SQL-запрос:

select count(*) 
from (
    select u.lastname, count(*) 
    from tbl_personel u 
    group  by u.lastname
) as tbl_aggr

Вот и все! Вам не нужно переводить каждый SQL-запрос в HQL. Собственный SQL - это волшебная палочка, а Таблица с разбивкой на страницы гораздо больше подходит для проекции DTO, чем для запроса HQL, который предназначен в основном для выборки сущностей.

person Vlad Mihalcea    schedule 23.03.2017

Назначьте вывод вашего запроса списку.

Query query = getEntityManager().createQuery("select u.lastname,count(*) from Personel u group by u.lastname;");

List<YourEntity> list = query.getResultList();

И ваш счет здесь ..

Integer.toString(list.size())

person Prashant Katara    schedule 13.09.2016
comment
Если количество результатов составляет 100000 записей, тогда это решение в порядке и имеет хорошую производительность? - person ali akbar azizkhani; 13.09.2016
comment
Вам нужно только посчитать или вы где-то показываете результаты запроса? Я не пробовал, но измените приведенный выше код в этом стиле и посмотрите результаты. query.getMaxResults (); - person Prashant Katara; 13.09.2016
comment
Я показываю результат разбивки на страницы. например, размер страницы = 10, и я показываю номер страницы = 2, и весь результат (по группе) равен 100000 - person ali akbar azizkhani; 13.09.2016
comment
Это очень неэффективно - person Kikin-Sama; 20.01.2018

1. Напишите свой HQL:

String hql = "select count(*) from (select u.lastname,count(*) from tbl_personel u group  by u.lastname)";

2. Создайте запрос из сеанса:

Query query = session.createQuery(hql);

3. Выполните запрос:

List listResult = query.list();
person Priyanka Patil    schedule 13.09.2016
comment
Это не hql-запрос. - person Priyanka Patil; 13.09.2016
comment
обратитесь к codejava.net/frameworks/hibernate/ - person Priyanka Patil; 13.09.2016
comment
hql доза не поддерживается hql из в подвыборке. проверьте еще раз - person ali akbar azizkhani; 13.09.2016