使用 SpringBoot 懒惰初始化角色集合失败

Posted

技术标签:

【中文标题】使用 SpringBoot 懒惰初始化角色集合失败【英文标题】:Failed to lazily initialize a collection of role with SpringBoot 【发布时间】:2019-01-23 09:51:02 【问题描述】:

我有一个基本的 SpringBoot 2.0.3.RELEASE 应用程序,它使用 Spring Initializer、JPA、嵌入式 Tomcat、Thymeleaf 模板引擎并将这些依赖项打包为可执行 JAR 文件。

我有一个名为 Company 的域对象:

@Entity
@Table(name="t_company")
public class Company implements Serializable 

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public Company() 
    



    /**
     * @param companyName
     */ 
    public Company(String companyName) 
        super();
        this.name = companyName;
    



    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotEmpty
    @Length(max = 100)
    private String name;


    @OneToMany(mappedBy = "company", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<User> users = new HashSet<>();

..

存储层:

public interface CompanyRepository extends CrudRepository<Company, Long> 

    @Query("select co from Company co join co.users us where co = ?1")
    Company companyUsers (Company company);


服务层:

@Service
@Transactional(readOnly = true)
public class CompanyService 

     @Autowired
     private CompanyRepository companyRepository;

     public Company companyUsers (Company company) 
        return companyRepository.companyUsers(company);
     


Junit 文件:

@Test
    public void testCompanyUsers() throws Exception 

        Iterable<Company> companies = companyService.findAll();
        Company company = companies.iterator().next();

        assertNotNull (company);

        company = companyService.companyUsers(company);
        assertTrue (((Collection<?>) company.getUsers()).size() > 0);           
    

但是当我运行测试时,我得到了这个错误:

延迟初始化角色集合失败: com.cor.backend.persistence.domain.backend.Company.users,不能 初始化代理 - 没有会话

【问题讨论】:

【参考方案1】:

请仔细阅读我的一篇文章:https://arnoldgalovics.com/lazyinitializationexception-demystified/

您的主要问题是您试图在事务之外访问实体引用。 您有多种选择:

在同一个逻辑事务中获取必要的数据 在您的 JPQL 查询中使用 FETCH JOIN 使用投影

更多关于预测的阅读:https://arnoldgalovics.com/using-projections-in-your-data-access-layer/

另外,考虑使用预测对性能的影响:https://arnoldgalovics.com/how-much-projections-can-help/

【讨论】:

【参考方案2】:

对于springboot,我们需要添加@Transactional(org.springframework.transaction.annotation.Transactional) 到我们使用延迟加载属性的类: testCompanyUsers()

import org.springframework.transaction.annotation.Transactional;

...
@Transactional
public void testCompanyUsers() throws Exception 
...

【讨论】:

【参考方案3】:

前段时间在类似的情况下找到了解决方案,在某些方法上使用了@Transactional(readOnly = true),并在我的实体类中填充了所有集合字段

【讨论】:

以上是关于使用 SpringBoot 懒惰初始化角色集合失败的主要内容,如果未能解决你的问题,请参考以下文章

懒惰初始化角色集合失败:someEnttiy.otherTitles

org.hibernate.LazyInitializationException:懒惰初始化角色集合失败(Hibernate + Spring)

Spring Boot 中的 Hibernate 无法懒惰地初始化角色集合,无法初始化代理 - 没有 Session 异常

Hibernate 无法懒惰地初始化角色集合 无法初始化代理 - 没有会话

无法懒惰地初始化角色集合,..无法初始化代理 - 无会话 - JPA + SPRING

在将对象转换为json期间,无法懒惰地初始化角色集合