如何从Java JPA的列表中延迟加载对象?

时间:2019-02-15 16:07:56

标签: spring-boot jpa lazy-loading

我拥有以下实体:DocumentType,UserGroup,User

DocumentType.java具有@ManyToMany用户组集:

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

我不断收到错误的问题:

  

原因:org.hibernate.LazyInitializationException:无法延迟初始化角色集合:it.akademija.wizards.entities.DocumentType.submissionUserGroups,无法初始化代理-没有会话

我想避免获取EAGER。如何实现此代码,以便我可以随机获取UserType的一部分,该UserGroup的一部分是DocumentType对象中的SubmissionUserGroups。

1 个答案:

答案 0 :(得分:0)

部分问题可能是您在@Transactional方法上使用了private注释。根据{{​​3}},这不起作用:

  

使用代理时,应仅将@Transactional注释应用于具有公共可见性的方法。如果使用@Transactional注释对受保护的,私有的或程序包可见的方法进行注释,则不会引发任何错误,但是带注释的方法不会显示已配置的事务设置。如果需要注释非公共方法,请考虑使用AspectJ(请参见下文)。

此外,我发现从文档类型中获取User的方式有些难以理解。问题的一部分是您遍历集合,找到内容然后再遍历另一个集合的时间。

UserRepository注入此类并在此处进行单独的查询可能会更容易(并且更符合Spring习惯用法)。如果此方法也是公开的,那么我相信它将被包含在同一事务中,这样您就不必承受不得不打开另一个会话的性能开销。

但是,您应该对此进行更多研究。您可能会发现这对其他帖子有帮助:docs