【问题标题】:Vaadin Spring and Hibernate: could not initialize proxy - no SessionVaadin Spring 和 Hibernate:无法初始化代理 - 没有会话
【发布时间】:2020-06-07 16:34:55
【问题描述】:

模型:

    @Entity
    ...
    public class ScolProgressionPopulation {    
       ...        
        @OneToMany(mappedBy = "population")
        private List<ScolProgressionSemestre> progressions;        
       ...
    }

回购:

    public interface ScolProgressionPopulationRepository extends JpaRepository<ScolProgressionPopulation, Long>

观点:

    @Route(value = "progression", layout = ApplicationLayout.class)
    @RouteAlias(value = "", layout = ApplicationLayout.class)
    public class ProgressionView extends Div {
           public ProgressionView(@Autowired ScolProgressionPopulationRepository scolProgressionPopulationRepository) {
               var items = scolProgressionPopulationRepository.findAll();

               // I try this..
               Hibernate.initialize(items);
               // and this ...
               Hibernate.initialize(items.get(0));

               // this works:
               System.out.println("this is ok:" +items.size());

               // but not this:
               System.out.println("err, could not initialize proxy - no Session :" +items.get(0).getProgressions().size());

我尝试了很多方法来实现延迟加载,(添加@Transactional、Hibernate.initialize...)

但我总是以这个错误结束:

org.springframework.beans.factory.BeanCreationException: 错误 用名字创建bean 'nc.unc.scolarite.lmd.progression.gui.ProgressionView': 豆 通过构造函数实例化失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:失败 实例化 [nc.unc.scolarite.lmd.progression.gui.ProgressionView]: 构造函数抛出异常;嵌套异常是 org.hibernate.LazyInitializationException:延迟初始化失败 角色集合: nc.unc.scolarite.lmd.progression.entities.ScolProgressionPopulation.progressions, 无法初始化代理 - 没有会话

PS:我不想使用 EAGER fetch。我想延迟加载数据。

【问题讨论】:

    标签: spring hibernate vaadin


    【解决方案1】:

    您可以在您的存储库中创建一个新方法,该方法使用join fetch 来获取相关实体,例如

    @Query("SELECT spp FROM ScolProgressionPopulation spp JOIN FETCH spp.progressions")
    public List<ScolProgressionPopulation> findAllWithProgressions();
    

    另一种方法是将@Transactional 注释添加到存储库中的方法(那么它不能是接口),它也可能适用于您视图中的方法。您可能需要为所有进度集合调用initialize,这不是很有效,因为它可能会创建许多数据库查询。

    @Transactional
    public List<ScrolProgressionPopulation> findAllWithProgressions() {
        val spps = findAll();
        for(ScrolProgressionPopulation spp: spps) {
            Hibernate.initialize(spp.getProgressions();
        }
        return spps;
    }
    

    编辑:如果你不想初始化所有项目,你可以这样做

    @Transactional
    public void initializeProgressions(ScrolProgressionPopulation spp) {
        Hibernate.initialize(spp.getProgressions());
    }
    

    并按需调用。

    【讨论】:

    • 我的 2 美分关于这两种方法的缩放:第一个解决方案可以使用 Entity Graphs 缩放。它将使管理多个惰性集合变得容易(并且不再需要 java 开发人员知道如何编写正确和高效的 JOIN 查询)。对于这里的第二种解决方案,我建议在扩展时在服务层中实现它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 2015-10-09
    • 2010-11-15
    • 1970-01-01
    • 2021-03-13
    • 2013-05-22
    • 1970-01-01
    相关资源
    最近更新 更多