API критериев Hibernate – как упорядочить по размеру коллекции?

StackOverflow https://stackoverflow.com/questions/1254306

  •  12-09-2019
  •  | 
  •  

Вопрос

Предполагая, что у меня есть классы User и UserGroup.Существует необязательная группа «1-многие» для ассоциации пользователей, и ассоциация сопоставляется с обеих сторон (сторона UserGroup через свойство под названием «members», которое является HashSet, сторона пользователя через свойство «группа»).

Как с помощью Criteria API запросить все группы, отсортированные по количеству членов группы?

(Редактировать) Когда я спрашивал об этом, я должен был указать, что разбиение на страницы выполняется в SQL, поэтому, если возможно, упорядочивание также должно выполняться в SQL.

Это было полезно?

Решение

Другой вариант — использовать аннотацию @Formula, которая по сути эквивалентна созданию вложенного выбора, чтобы вы могли получить свои значения.

В рассматриваемом свойстве/члене объектов БД (который вы должны создать) добавьте аннотацию к методу получения, например:

@Formula ("(выберите count (table_name.id) из таблицы, где что угодно ...)") public getnewproperty {return newproperty;}

Затем нацельтесь на члена напрямую, чтобы получить значения вашего счетчика...

Примечание:Имейте в виду, что при указании sql в аннотации формулы вы должны указывать имена полей непосредственно при ссылке на текущую таблицу объектов (this), поскольку спящий режим сам справляется с этим.Поэтому в вашем предложении WHERE просто используйте ID или что-то еще при ссылке на текущую таблицу объектов, которая, как я подозреваю, является UserGroup.

Мне нужен был установщик для моего нового свойства, чтобы спящий режим работал и не давал компилятору жаловаться.

Могут быть и другие умные способы использования @Formula, но я новичок в этом, и, похоже, документации по этому вопросу не так уж и много...

Если вы никогда раньше не использовали вложенные SELECTS, возможно, вам стоит сначала просто воссоздать их в sql - это мне помогло.

Надеюсь это поможет

Другие советы

По умолчанию это невозможно с использованием Citeria API, но вы можете расширить класс org.hibernate.criterion.Order.Эта статья о том, как расширить этот класс: http://blog.tremend.ro/2008/06/10/how-to-order-by-a-custom-sql-formulaexpression-when-using-hibernate-criteria-api

Мое решение:

public class SizeOrder extends Order {

    protected String propertyName;
    protected boolean ascending;

    protected SizeOrder(String propertyName, boolean ascending) {
        super(propertyName, ascending);
        this.propertyName = propertyName;
        this.ascending = ascending;
    }

    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        String role = criteriaQuery.getEntityName(criteria, propertyName) + '.' + criteriaQuery.getPropertyName(propertyName);
        QueryableCollection cp = (QueryableCollection) criteriaQuery.getFactory().getCollectionPersister(role);

        String[] fk = cp.getKeyColumnNames();
        String[] pk = ((Loadable) cp.getOwnerEntityPersister())
                .getIdentifierColumnNames();
        return " (select count(*) from " + cp.getTableName() + " where "
                + new ConditionFragment()
                        .setTableAlias(
                                criteriaQuery.getSQLAlias(criteria, propertyName)
                        ).setCondition(pk, fk)
                    .toFragmentString() + ") "
                + (ascending ? "asc" : "desc");
    }

    public static SizeOrder asc(String propertyName) {
        return new SizeOrder(propertyName, true);
    }
    public static SizeOrder desc(String propertyName) {
        return new SizeOrder(propertyName, false);
    }
}

Метод toSqlString основан на классе org.hibernate.criterion.SizeExpression.(Источник: http://javasourcecode.org/html/open-source/hibernate/hibernate-3.6.0.Final/org/hibernate/criterion/SizeExpression.java.html)

Пример использования:

hibernateSession.createCriteria(UserGroup.class).addOrder( SizeOrder.asc("members") ).list();

это будет список групп пользователей, упорядоченных по размеру участников по возрастанию, где «члены» — это коллекция пользователей в сущности UserGroup.

Вероятно, вы могли бы сделать это, определив «производное свойство» для вашей сущности, которое будет доступно только для чтения и возвращает размер коллекции внутри этой сущности.Самый простой способ определить производное свойство: задокументировано здесь:

Обновление, вставка (необязательно - по умолчанию true):Указывает, что сопоставленные столбцы должны быть включены в операторы SQL Update и/или вставить.Установка оба на false позволяет чистому «полученному» свойству, значение которого инициализируется из какого -либо другого свойства, которое отображается на одном и том же столбце (ы), или с помощью триггера или другого применения.

После определения свойства вы сможете использовать имя свойства в качестве условия заказа в API критериев, как и любое другое свойство.Хотя сам я этого не пробовал.

Если это сработает, то, скорее всего, это будет выполнено как сортировка в памяти, поскольку она не сможет сопоставить ее с SQL.Если это проблема, то по той же ссылке выше описано, как реализовать производное свойство с использованием специального фрагмента SQL:

Мощная особенность - это свойства.Эти свойства по определению только для чтения.Значение свойства вычисляется во время загрузки.Вы объявляете вычисление как выражение SQL.Затем это переводится на подложку Select Clause в запросе SQL, который загружает экземпляр:

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top