Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring@Async:惰性集合上的null hibernate会话_Java_Spring_Hibernate_Hibernate Session - Fatal编程技术网

Java Spring@Async:惰性集合上的null hibernate会话

Java Spring@Async:惰性集合上的null hibernate会话,java,spring,hibernate,hibernate-session,Java,Spring,Hibernate,Hibernate Session,我正在服务层方法上使用@Async注释 当我急切地加载@OneToMany集合字段时,一切正常,但当我尝试访问延迟加载的元素时,我发现HibernateSessionImplementorobjectsession为空。这显然给了我一个例外: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: .... 这是我的收藏栏: @OneToMany(mappe

我正在服务层方法上使用
@Async
注释

当我急切地加载@OneToMany集合字段时,一切正常,但当我尝试访问延迟加载的元素时,我发现Hibernate
SessionImplementor
object
session
为空。这显然给了我一个例外:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
....    
这是我的收藏栏:

@OneToMany(mappedBy="abc", fetch=FetchType.LAZY, cascade=CascadeType.REMOVE)
@OrderBy(value="xsd asc")
@JsonIgnore
private Set<Item> items = new HashSet<Item>();

Spring的事务上下文是使用保存的。这意味着您的SessionFactory仅对发送请求的线程可用,因此,如果您创建一个新线程,您将得到一个
null
和一个相应的异常

您的
@Async
方法所做的是在另一个线程中使用来运行您的方法。因此,上述问题发生在您的服务中

我引用《春天》的文件:

针对单个JPA的PlatformTransactionManager实现 实体管理工厂从指定的服务器绑定JPA EntityManager 工厂到线程,可能允许一个线程绑定 每个工厂的实体经理。共享身份管理器创建者和 @PersistenceContext知道线程绑定的实体管理器和 自动参与此类交易。使用其中一个是 支持此事务管理的JPA访问代码需要 机制

如果你想保留你的注释,那么你应该看看Hibernate,然后自己管理会话

有关更多信息,请参阅。

在正常情况下(没有
@Async
),事务通过调用层次结构从一个Spring组件传播到另一个组件

@Transactional
Spring
@Component
调用带有
@Async
注释的方法时,不会发生这种情况。异步方法的调用由任务执行者在稍后时间进行调度和执行,因此作为“新鲜”调用处理,即没有事务上下文。如果
@Async
方法(或声明它的组件)本身不是
@Transactional
,Spring将不会管理任何需要的事务


尝试注释调用
@Async
方法的方法,并告诉我们是否有效。

我也有同样的问题,花了几天时间试图找到解决方案,最后终于找到了解决方案。我想分享我为那些可能有同样问题的人找到的细节

1-您的
@Async
-带注释的方法应该在单独的bean中声明,而不是
@Controller
-或
@RestController
-带注释的bean中声明

第二,您当然需要声明方法
@Transactional
,该方法是从
@Async
声明的方法中调用的。但是,从
@Async
方法调用的第一个方法必须定义为
@Transactional
。我在方法执行堆栈的第二级或第三级使用了
@Transactional
方法,因此问题没有得到解决,我花了两天时间试图弄清楚到底发生了什么

所以最好的办法就是

@Controller
ControllerBean {

    @Autowired
    AsyncService asyncService;

    public controllerMethod() {
        asyncService.asyncMethod();
    }
}

@Service
AsyncService {
    @Autowired
    TransactionalService transactionalService;

    @Async
    public asyncMethod() {
        transactionalService.transactionalMethod();
    }
}

@Service
TransactionalService {
    @Autowired
    SomeOtherService someOtherService;

    @Autowired
    EntityRepository entityRepository;

    @Transactional
    public transactionalMethod() {
        Entity entity = entityRepository.findOne(12345);

        someOtherService.doWork(entity);
    }
}

@Service
SomeOtherService {

    @Autowired
    EntityRepository entityRepository;

    @Transactional
    public doWork(Entity entity) {
        // fetch lazy properties, save, etc. without any session problems...
        entity.getLazyProperties(); 

        entityRepository.save(entity);
    }
}

这取决于映射如何发生以及在何处发生

如果要将@Async惰性加载一起使用,则使用@Transactional声明的方法必须实现惰性加载的逻辑


如果在@Transactional外部初始化了惰性加载,则加载将不起作用。

是否使用Spring管理的SessionFactory和TransactionManager?。你能展示这个方法的代码吗?这个方法是在加载实体还是只是在访问它?@eldermel,我已经更新了我的答案。在这种情况下,你可以实现一个允许跨线程和调用线程保留会话的方法。我在使用@async时也遇到了同样的问题。我尝试了很多事情,最后通过打开一个新的会议,做一些事情,然后结束会议来处理它。我不确定这是否是一个理想的解决方案,但考虑到hibernate会话和线程在一起时有一些个人问题,我对这个解决方案很满意。谢谢你的回答。我的方法已经是事务性的了!
@Controller
ControllerBean {

    @Autowired
    AsyncService asyncService;

    public controllerMethod() {
        asyncService.asyncMethod();
    }
}

@Service
AsyncService {
    @Autowired
    TransactionalService transactionalService;

    @Async
    public asyncMethod() {
        transactionalService.transactionalMethod();
    }
}

@Service
TransactionalService {
    @Autowired
    SomeOtherService someOtherService;

    @Autowired
    EntityRepository entityRepository;

    @Transactional
    public transactionalMethod() {
        Entity entity = entityRepository.findOne(12345);

        someOtherService.doWork(entity);
    }
}

@Service
SomeOtherService {

    @Autowired
    EntityRepository entityRepository;

    @Transactional
    public doWork(Entity entity) {
        // fetch lazy properties, save, etc. without any session problems...
        entity.getLazyProperties(); 

        entityRepository.save(entity);
    }
}