Размер коллекции Hibernate без инициализации - PullRequest
36 голосов
/ 26 мая 2010

Есть ли способ подсчитать размер связанной коллекции без инициализации?

, например

Select count(p.children) from Parent p

(есть веская причина, почему я не могу сделать это любым другим способом, поскольку мое предложение where более сложное, а предложение from - полиморфный запрос)

Спасибо.

Ответы [ 3 ]

59 голосов
/ 26 мая 2010

Возможным решением, отличным от запросов, может быть сопоставление children с lazy="extra" (в нотации XML). Таким образом, вы можете выбрать Parent с любым запросом, который вам нужен, затем вызвать parent.getChildren().size() без загрузки всей коллекции (выполняется только запрос типа SELECT COUNT).

С аннотациями это будет

@OneToMany
@org.hibernate.annotations.LazyCollection(
org.hibernate.annotations.LazyCollectionOption.EXTRA
)
private Set<Child> children = new HashSet<Child>();

Обновление: Цитата из Сохранение Java с Hibernate , ch. 13.1.3:

Прокси инициализируется, если вы вызываете любой метод, который не является получателем идентификатора метод, коллекция инициализируется, если вы начинаете перебирать ее элементы или если Вы вызываете любую из операций управления коллекцией, например size() и contains(). Hibernate предоставляет дополнительную настройку, которая в основном полезна для больших коллекций; они могут быть отображены как очень ленивый . [...]

[Отображено как указано выше], коллекция больше не инициализируется, если вы вызываете size(), contains() или isEmpty() - база данных запрашивается для получения необходимой информации. Если это Map или List, операции containsKey() и get() также запрашивает базу данных напрямую.

Итак, с сущностью, отображенной, как указано выше, вы можете сделать

Parent p = // execute query to load desired parent
// due to lazy loading, at this point p.children is a proxy object
int count = p.getChildren().size(); // the collection is not loaded, only its size
1 голос
/ 13 июня 2012

Вы можете использовать Session # createFilter, который является формой HQL, которая явно работает с коллекциями. Например, вы упоминаете «Родитель и дети», поэтому, если у вас есть «Человек р», наиболее простой формой будет:

session.createFilter( p.getChildren(), "" ).list()

Это просто возвращает вам список детей. Важно отметить, что возвращаемая коллекция не является «живой», она никак не связана с p.

Интересная часть вытекает из второго аргумента. Это фрагмент HQL. Вот например, вы можете захотеть:

session.createFilter( p.getChildren(), "select count(*)" ).uniqueResult();

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

session.createFilter( p.getChildren(), "select count(*) where this.age > 18" ).uniqueResult();

Обратите внимание, что в предложении нет. То есть предложение from подразумевается от ассоциации. Элементы коллекции имеют псевдоним «this», поэтому вы можете ссылаться на него из других частей фрагмента HQL.

0 голосов
/ 06 апреля 2015

Вы можете сделать то же самое, как это:

@Override
public FaqQuestions getFaqQuestionById(Long questionId) {
    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    FaqQuestions faqQuestions = null;
    try {
        faqQuestions = (FaqQuestions) session.get(FaqQuestions.class,
                questionId);
        Hibernate.initialize(faqQuestions.getFaqAnswers());

        tx.commit();
        faqQuestions.getFaqAnswers().size();
    } finally {
        session.close();
    }
    return faqQuestions;
}

Просто используйте faqQuestions.getFaqAnswers (). Size () в вашем контроллере, и вы получите размер, если лениво инициализировать список, без извлечения самого списка..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...