【问题标题】:@Scheduled @Transactional lazy init collection error - no proxy@Scheduled @Transactional 惰性初始化收集错误 - 没有代理
【发布时间】:2015-11-18 08:09:23
【问题描述】:

我们已经使用 Spring 4、Hibernate、存储库和 JPA 开发网站大约一年了。我们使用 OpenEntityManagerInViewFilter 在通过端点检索数据时保持会话打开,但最近一直在使用计划的操作,现在遇到了问题。

我们在一个类中有一个带有@Scheduled 注解的方法,在另一个类中有另一个带有@Transactional 注解的方法。调用方法在文件系统上查找数据并将其传递给第二个类/方法。

这是代码的简化版本:

<code>
// metadataRepository 
    @Transactional
    public Metadata findOneById(String uuid);


    @Transactional
    public void processQueueMessages(Map<String, MessageAttributeValue> attributes ) throws IOException{
        Metadata metadata = null;
        try{
            metadata = metadataRepository.findOneById(uuid);

            // REST call to get list of locations
            GeotaggerList locationList = response.getResult();

            // this call just maps fields, no database interaction
            Map<String, GeoLocation> locationNameMap = metadataService.getKwebLocations(locationList, null);
            for (Map.Entry<String, GeoLocation> entry : locationNameMap.entrySet()){
                entry.getValue().setMetadata(metadata);
                metadata.getGeoLocations().add(entry.getValue());  //fails
            }
            metadataService.save(metadata, username);
            }
        } catch (Exception e){
            e.printStackTrace();
            return;
        }
</code>

调用 processQueueMessages 的方法/类有一个@Scheduled 注解。我尝试在调用者上添加@Transactional 注释,但无济于事。

我尝试了几种放置注释的变体,但总是出现此错误: org.hibernate.LazyInitializationException:无法延迟初始化角色集合:.domain.Metadata.geoLocations,无法初始化代理 - 无会话

我不能在 Metadata 域对象的定义中进行 Eager fetch,因为它在很多我们不想进行 Eager 加载的地方使用。

我愿意接受建议。

【问题讨论】:

  • 根据您使用的版本,您可能可以使用实体图为该查询急切加载对象。
  • 我也有同样的问题。特定版本是否存在错误?
  • 自 JPA 2.1 起支持实体图

标签: java hibernate jpa scheduled-tasks transactional


【解决方案1】:

您可以尝试使用休眠获取配置文件。

https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/performance.html#performance-fetching-profiles

基本上,您在模型上默认保持相同的延迟加载,但创建一个快速加载您的地理位置属性的获取配置文件。然后,当您从计划的方法加载元数据时,激活您的获取配置文件。

【讨论】:

    【解决方案2】:

    metadata 对象在从 metadataRepository 中检索后似乎已经脱离了事务会话,否则抛出惰性异常是没有意义的。检查metadataRepository.findOneById(uuid) 是否没有在单独的事务中运行,例如将其标记为REQUIRES_NEW

    为了防止延迟加载异常,您应该通过简单地调用metadata.getGeoLocations().isEmpty() 或使用fetch join 查询来预加载调用metadataRepository.findOneById 内的数据以急切地检索数据

    【讨论】:

      【解决方案3】:

      经过大量搜索,答案很简单,就像通常一样。我使用了一个配置类,它需要一个注解 @EnableTransactionManagement

      答案在 Spring Data 文档中 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html

      我一定已经读了十几遍了,但错过了关键的陈述。

      【讨论】:

        猜你喜欢
        • 2021-08-20
        • 2021-06-15
        • 2016-11-10
        • 2020-11-25
        • 1970-01-01
        • 2012-09-14
        • 1970-01-01
        • 2021-01-30
        • 2013-10-22
        相关资源
        最近更新 更多