JPA 会话与 Vertx EventBus 使用者中的惰性集合



我在 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 發生了 invoking 方法。

进一步检查显示与此 persisent 集相关的会话为 null,因此调用Hibernate.initialize(system.getSomeCollection())将引发异常。

这两种方法都解决了这个问题,但这不是一个选择,因为如果不打算使用集合,则每次都无法获取集合。

在事件总线使用者之外的任何位置调用服务会为我提供一个可以按需初始化的集合。

我做错了什么?

好吧,您应该将传入的请求处理逻辑包装到单个事务方法中,以防止实体在对systemService.getSystemWithHistoryFrom()systemService.update()的调用之间分离。像@Transactional public void SystemService.getSystemHistoryDoImportantStuffAndSaveResults().

或者,您可以自定义由systemService.getSystemWithHistoryFrom()执行的查询,以JOIN FETCH所有必需的集合,并使集合在实体本身中延迟提取。但是,将整个业务逻辑包装在事务中要安全得多,因为它除了解决您的问题外,还会强制实施事务隔离。

最新更新