为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

叮当猫咪 2021-06-29 15:23:08
我知道有很多“无法初始化代理 - 没有会话”的问题,但我没有找到我的问题的任何答案。所以问题是,当我委托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        }    }}个人服务@Statelesspublic class PersonService extends Service<PersonService,Person> { ... }人豆@Named @ViewScopedpublic 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    }}
查看完整描述

1 回答

?
Helenr

TA贡献1780条经验 获得超4个赞

我将假设此服务是 Java EE 或 Spring 事务服务。声明式事务是基于代理的。当您使用依赖注入获取服务实例并调用事务方法时,您实际上调用了包装服务的事务代理的方法:

client ----------> transactional proxy -----------> service
                    - start the transaction
                    - call the service
                    - commit
                    -return the value returned by the service

当你打电话时fetchLazy(),一切正常:

  • 交易开始,

  • 然后使用实体管理器找到实体并初始化其公司代理,

  • 然后事务被提交

  • 然后你会得到带有初始化公司的实体。

当你打电话时fetch(),这就是发生的事情

  • 交易开始,

  • 构造了一个 FetchBuilder

  • 然后事务被提交

  • 然后你得到 FetchBuilder

这个事务实际上是无用的,因为你从不使用实体管理器。

现在当你调用fetch()返回的构建器时会发生什么?它调用FetchBuilderfetchLazyservice实例变量。这service是实际服务实例的实例,而不是包装服务实例的代理实例,因为您使用this, 从服务实例本身对其进行了初始化。因此,您绕过了代理,因此这些不是find()包含对公司的调用和初始化的事务。


查看完整回答
反对 回复 2021-07-14
  • 1 回答
  • 0 关注
  • 143 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信