@OneToMany ограничение размера списка отображения - PullRequest
12 голосов
/ 25 октября 2011

Есть ли способ ограничить размер списка отношения @OneToMany в JPA?Вот мой пример кода:

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST)
private List<Comment> commentList;

Я использую реализацию EclipseLink 2.3 JPA.Заранее спасибо.

Ответы [ 4 ]

16 голосов
/ 26 октября 2011

Часть спецификации проверки компонентов (JSR-303) представляет собой примечание @Size(min=, max=):

Поддерживаемые типы: String, Collection, Map и arrays. Проверьте, находится ли размер аннотированного элемента между минимальным и максимальным (включительно).

Вы можете проверить коллекцию.

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST)
@Size(min=1, max=10)
private List<Comment> commentList;
3 голосов
/ 16 ноября 2015

Настоящая проблема - сама коллекция.Вы должны не моделировать бизнес-домен таким образом.Это решение (для коллекций, помеченных @OneToMany) применимо только для небольших коллекций (десятки объектов), но не для больших (тысячи объектов), что вполне может быть в случае с комментариями.Вы действительно должны остерегаться с ними, поскольку они могут быстро выйти из-под контроля.В настоящее время я использую их только для моделирования коллекции Role s, связанной с Account, потому что я знаю, что ни одна учетная запись не будет иметь более 9 ролей в моем домене, и потому что роли, в которых находится учетная запись, таковы.очень важно для работы с учетной записью.Для всех других отношений m-to-n я использую простые старые запросы.

Вместо добавления коллекции комментариев к вашему объекту, добавьте ссылку на объект в Comment и явно получите комментарии, которые вы хотите, используя запрос.

Определите именованный запрос на Comment, чтобы получить комментарии для определенного объекта (давайте используем Article):

@Entity
@NamedQueries(value={
    @NamedQuery(name=Comment.FOR_ARTICLE, query=
        "SELECT c FROM Comment c WHERE c.article = :article"
    )
})
public class Comment {
    // ...
    @ManyToOne
    @JoinColumn(name = "articleId")
    private Article article;
}

Тогдаиспользуйте этот именованный запрос icw Query.setMaxResults и Query.setFirstResult , чтобы явно контролировать, сколько результатов получить и разрешить подкачку и т. д .:

@PersistenceContext
EntityManager em;

Article theArticle = ...;

Query query = em.createNamedQuery(Comment.FOR_ARTICLE, Comment.class);
query.setParameter("article", theArticle);
query.setFirstResult(0);
query.setMaxResults(10);
List<Comment> comments = (List<Comment>) query.getResultList();

Для выполненияпейджинг, просто setFirstResult до первого результата, соответствующего странице, которую вы хотите отобразить.Например, чтобы показать результаты 20 .. 29, вы бы позвонили setFirstResult(20).

2 голосов
/ 26 октября 2011

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

Вы делаете это из-за производительности? Если это так, то вы можете использовать Lazy стиль извлечения и использовать аннотацию Batchsize , чтобы указать, сколько вы хотите получить за один раз:

* исправление: @Batchsize - это функция Hibernate

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST, fetch=LAZY)
@BatchSize(size=16)
private List<Comment> commentList;

Затем в вашем коде просто выполняйте итерацию / цикл в том месте, куда вы хотите в этой сопоставленной коллекции.

В любом случае, из моего опыта «взлома» отображений для выполнения задач, для которых предназначены Критерии / Запросы, это не плодотворное усилие, когда вам нужно больше контроля или настройки производительности, чем явно предоставляет @OneToMany, лучшим способом может быть просто сделайте запрос.

0 голосов
/ 06 октября 2012

Нет настоящего ортодоксального способа сделать это. Я бы сделал отношение ленивым, запрос для родительских объектов. После того, как подопечные не инициализируют ленивый список и запускают другой запрос на основе первого запроса, который выполняется на дочерней таблице. Таким образом, вы можете ограничить набор результатов по основным критериям, а не по критериям объединения. Или вы можете запустить только второй запрос (только для дочерней таблицы) с поддержкой нумерации страниц.

...