У меня есть эти сущности: 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.




Вероятно, часть вашей проблемы связана с тем, что вы использовали аннотацию @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 в мой контроллер.