我在Vert.x eventbus上创建了一个消费者:
@Autowired
private Vertx vertx;
public void registerConsumer() {
EventBus eb = vertx.eventBus();
eb.consumer("action.request", (Message<String> msg) -> {
handleIncomingRequest(msg);
});
}
在handleIncomingRequest
链中,我调用服务从psql数据库中获取实体:
private void handleIncomingRequest(Request request) {
SystemNode system = systemService
.getSystemWithHistoryFrom(request.getUuid());
// All lazily initialized collections unavailable here
systemService.update(system);
}
在上面的方法中,我尝试对SystemNode
对象中的集合执行一些操作。但是,永远不会获取此对象上的延迟初始化集合。我尝试过设置@Fetch(FetchMode.JOIN)
和FetchType.EAGER
。当我检查对象时,我可以看到它是一个持久集,它向我显示以下错误:
com.sun.jdi.InvocationException发生了调用方法。
进一步检查显示与此persisent集相关的会话为null,因此调用Hibernate.initialize(system.getSomeCollection())
将引发异常。
这两种方法都解决了这个问题,但这不是一个选项,因为如果它不会被使用,那么每次收集太大而无法获取。
在eventbus消费者之外的任何地方调用服务,为我提供了一个可以按需初始化的集合。
我做错了什么?
答案 0 :(得分:2)
好吧,您应该将传入的请求处理逻辑包装到单个事务方法中,以防止实体在systemService.getSystemWithHistoryFrom()
和systemService.update()
的调用之间分离。像@Transactional public void SystemService.getSystemHistoryDoImportantStuffAndSaveResults()
这样的东西。
或者,您可以自定义由systemService.getSystemWithHistoryFrom()
执行的查询到JOIN FETCH
所有必需的集合,并保持集合在实体本身内延迟获取。但是,将整个业务逻辑包装在事务中会更加安全,因为除了解决问题之外,它还会强制执行事务隔离。