服务委托抛出“LazyInitializationException:无法初始化代理 - 没有会话”

我知道有很多“无法初始化代理 - 没有会话”的问题,但我没有找到我的问题的任何答案。


所以问题是,当我委托fetchLazy方法时,它会抛出上面提到的异常。这是我的服务类的简化版本:


服务


public abstract class Service<S extends Service<S,E>, E extends Entity> {

    @PersistenceContext private EntityManager entityManager;


    // person = personService.fetchLazy(person, Person::getCompany); OK

    public E fetchLazy(E entity, Function<E,?> proxyMapper) {

        E attachedEntity = entityManager.find(entity.getClass(), entity.getId());

        Object proxy = proxyMapper.apply(attachedEntity);

        if (!Hibernate.isInitialized(proxy)) { Hibernate.initialize(proxy); }

        return attachedEntity;

    }


    // person = personService.fetch(person).lazy(Person::getCompany); EXCEPTION

    public FetchBuilder fetch(E entity) { return new FetchBuilder((S) this, entity); }


    public class FetchBuilder {

        private final S service; private final E entity;

        LazyFetchBuilder(E e, S s) { this.entity = e; this.service = s; }

        public E lazy(E entity, Function<E,?> proxyMapper) {

             return service.fetchLazy(entity, proxyMapper); // DELEGATE

        }

    }

}

个人服务


@Stateless

public class PersonService extends Service<PersonService,Person> { ... }

人豆


@Named @ViewScoped

public class PersonBean implements Serializable {

    @EJB private PersonService personService;


    @PostConstruct public void init()  {

        person = personService.getById(id);

        person = personService.fetchLazy(person, Person::getCompany); // OK

        person = personService.fetch(person).lazy(Person::getCompany); // EXCEPTION

    }

}


叮当猫咪
浏览 144回答 1
1回答

Helenr

我将假设此服务是 Java EE 或 Spring 事务服务。声明式事务是基于代理的。当您使用依赖注入获取服务实例并调用事务方法时,您实际上调用了包装服务的事务代理的方法:client&nbsp;---------->&nbsp;transactional&nbsp;proxy&nbsp;----------->&nbsp;service &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;start&nbsp;the&nbsp;transaction &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;call&nbsp;the&nbsp;service &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;commit &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-return&nbsp;the&nbsp;value&nbsp;returned&nbsp;by&nbsp;the&nbsp;service当你打电话时fetchLazy(),一切正常:交易开始,然后使用实体管理器找到实体并初始化其公司代理,然后事务被提交然后你会得到带有初始化公司的实体。当你打电话时fetch(),这就是发生的事情交易开始,构造了一个 FetchBuilder然后事务被提交然后你得到 FetchBuilder这个事务实际上是无用的,因为你从不使用实体管理器。现在当你调用fetch()返回的构建器时会发生什么?它调用FetchBuilderfetchLazy的service实例变量。这service是实际服务实例的实例,而不是包装服务实例的代理实例,因为您使用this, 从服务实例本身对其进行了初始化。因此,您绕过了代理,因此这些不是find()包含对公司的调用和初始化的事务。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java