0

I am having these Entities: DocumentType, UserGroup, User

DocumentType.java has @ManyToMany Set of 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 has @ManyToMany Set of User:

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

What I want to do implement this code:

    @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);
}

The problem that I keep getting error:

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

I want to avoid EAGER fetching. How to implement this code so I can randomly get User that is a part of UserGroup which is a part of SubmissionUserGroups in DocumentType object.

Andyally
  • 863
  • 1
  • 9
  • 22

1 Answers1

0

Part of your problem is likely that you've used the @Transactional annotation on a private method. According to the docs, this doesn't work:

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.

In addition, I find the way you get a User from the document type a bit hard to understand. Part of the issue there is the number of time you stream through collections, find something, and then stream through another collection.

It might be easier (and more in line with Spring idioms) to inject the UserRepository into this class and do a separate query here. If this method is also public, I believe it would be included in the same transaction so you wouldn't suffer the performance overhead of having to open another session.

However, you should do some more research on this. You might find this other post helpful: How to load lazy fetched items from Hibernate/JPA in my controller.

theonlyrao
  • 416
  • 2
  • 13