我知道有很多“无法初始化代理 - 没有会话”的问题,但我没有找到我的问题的任何答案。所以问题是,当我委托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()
返回的构建器时会发生什么?它调用FetchBuilderfetchLazy
的service
实例变量。这service
是实际服务实例的实例,而不是包装服务实例的代理实例,因为您使用this
, 从服务实例本身对其进行了初始化。因此,您绕过了代理,因此这些不是find()
包含对公司的调用和初始化的事务。
添加回答
举报
0/150
提交
取消