Как лениво загрузить объект из списков в Java JPA?

У меня есть эти сущности: DocumentType, UserGroup, User

DocumentType.java имеет @ManyToMany Set UserGroup:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "review_type", joinColumns = @JoinColumn(name = "doc_type"),
        inverseJoinColumns = @JoinColumn(name = "user_group_id") )
private Set<UserGroup> reviewUserGroups;

UserGroup.java имеет набор пользователей @ManyToMany:

    @ManyToMany
@JoinTable(name = "group_users", joinColumns = @JoinColumn(name = "group_id"),
        inverseJoinColumns = @JoinColumn(name = "user_id"))
private Set<User> users;

Что я хочу сделать, чтобы реализовать этот код:

    @Transactional
private void createDocuments(int avgDocsPerUser) {
    List<DocumentType> documentTypes = documentTypeRepository.findAll();
    int documentTypesCount = documentTypes.size();
    List<User> users = userRepository.findAll().stream().filter(user -> !user.isAdmin()).collect(Collectors.toList());
    int usersCount = users.size();
    int documentsToCreate = (int) Math.floor(Math.random() * (usersCount * avgDocsPerUser)) + 1;
    List<Document> documentList = new ArrayList<>();

    while (documentList.size() < documentsToCreate) {
        DocumentType documentType = documentTypes.get((int) Math.floor(Math.random() * documentTypesCount));
        User user = documentType
                .getSubmissionUserGroups()
                .stream().findAny()
                .get().getUsers()
                .stream().findAny().get();
        // create new document here and add User info to it
    }
    documentRepository.saveAll(documentList);
}

Проблема, что я продолжаю получать ошибку:

Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: it.akademija.wizards.entities.DocumentType.submissionUserGroups, could not initialize proxy - no Session

Я хочу избежать извлечения EAGER. Как реализовать этот код, чтобы я мог случайным образом получить пользователя, который является частью UserGroup, который является частью SubmissionUserGroups в объекте DocumentType.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
0
335
1

Ответы 1

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

When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

Кроме того, я считаю, что способ получения User из типа документа немного сложен для понимания. Часть проблемы заключается в том, сколько раз вы просматриваете коллекции, находите что-то, а затем просматриваете другую коллекцию.

Может быть проще (и больше в соответствии с идиомами Spring) внедрить UserRepository в этот класс и выполнить здесь отдельный запрос. Если этот метод также является общедоступным, я полагаю, что он будет включен в ту же транзакцию, чтобы вы не столкнулись с накладными расходами, связанными с открытием другого сеанса.

Тем не менее, вам следует провести дополнительные исследования по этому вопросу. Вам может быть полезен этот другой пост: Как загрузить лениво извлеченные элементы из Hibernate/JPA в мой контроллер.

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