简体   繁体   English

@Transactional 上的 Spring Hibernate LazyInitializationException

[英]Spring Hibernate LazyInitializationException on @Transactional

I have a service that runs async task at startup that runs recursively:我有一个在启动时运行异步任务的服务,它以递归方式运行:

@Service
public class TaskService {

    private final TaskRepository taskRepository;

    @Inject
    public TaskService(TaskRepository taskRepository) {
        this.taskRepository= taskRepository;
    }

    private final int currentTaskId = -1;

    @Transactional
    @PostConstruct
    private void init() {
        taskRepository.findByClosedDateIsNull().forEach(taskRepository::delete);
        runTask();
    }

    @Async
    @Transactional
    private void runTask() {
        if (!getCurrent().isPresent()) {
            Task task = new Task();
            //set props
            currentTaskId = taskRepository.save(task).getId(); 
        }
        Util.sleep(5000); //wrapper for simple Thread.sleep(long l).
        Task task = getCurrent().get();
        if (task.getEvents().size > 0) {
            //bussiness logic
            Util.sleep(1000);
        }
        runTask();
    }

    @Transactional(readOnly = true)
    private Optional<Task> getCurrent() {
        return taskRepository.findOneById(currentTaskId).map(task -> {
            task.getEvents().size(); //throws the error here
            return task;
        });
    }

}

StackTrace:堆栈跟踪:

Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.test.domain.Task.events, could not initialize proxy - no Session at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:576) at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:215) at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:156) at org.hibernate.collection.internal.PersistentSet.size(PersistentSet.java:160) at com.test.service.TaskService.lambda$getCurrent$5(TaskService.java:135) at java.util.Optional.map(Optional.java:215) at com.test.service.TaskService.getCurrent(TaskService.java:134) at com.test.service.TaskService.runTask(TaskService.java:163) at com.test.service.TaskService.init(TaskService.java:66) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Me引起:org.hibernate.LazyInitializationException:未能延迟初始化角色集合:com.test.domain.Task.events,无法初始化代理 - 在 org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection. java:576) at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:215) at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistent:15.orginternal.java:215) .PersistentSet.size(PersistentSet.java:160) at com.test.service.TaskService.lambda$getCurrent$5(TaskService.java:135) at java.util.Optional.map(Optional.java:215) at com.test .service.TaskService.getCurrent(TaskService.java:134) at com.test.service.TaskService.runTask(TaskService.java:163) at com.test.service.TaskService.init(TaskService.java:66) at sun。 reflect.NativeMethodAccessorImpl.invoke0(Native Me thod) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:365) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:310) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133) ... 21 common frames omitted thod) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:365) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetaProcessdata.Initjava. beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133) ...省略了21个常用帧

I also tried Hibernate.initialize(Object proxy);.我也试过 Hibernate.initialize(Object proxy);。 OpenViewSessionFilter is not the solution for me. OpenViewSessionFilter 不是我的解决方案。 I don't want to set this collection EAGER.我不想设置这个集合 EAGER。

I found a solution (don't know if it's a bad practice, but it works for me).我找到了一个解决方案(不知道这是否是一种不好的做法,但它对我有用)。 Just create a default method in your JpaRepository and annotate it with @Transactional.只需在您的 JpaRepository 中创建一个默认方法并使用 @Transactional 对其进行注释。 In the service call this method.在服务中调用这个方法。

对我来说,当我在第一个函数调用中删除@Transactional (在您的情况下这将是init() )并将@Async功能移动到一个单独的 bean 时,它解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM