Quarkus集成Reactive Hibernate后接口执行查询返回报错如何解决
问题根因
你触发该报错的核心原因是Jackson序列化器试图直接序列化Mutiny的Uni类型对象:Quarkus的RESTEasy Reactive只会自动处理方法直接返回的最外层Uni,你代码里把嵌套的Uni塞到Response body中,Jackson无法识别Mutiny的内部类,就会抛出该序列化异常。
除此之外你的代码还有3个明显的逻辑错误,会导致流程无法正常执行:
- 错误使用
transform处理返回Uni的回调,生成了Uni<Uni<Long>>的嵌套结构,嵌套的内层Uni无法被RESTEasy自动解析 createNewFolders方法漏写return语句,实际返回值为null,会触发空指针异常calladdFile方法使用void返回值,异步操作没有拼接进主响应链,属于"fire and forget"的错误写法,会导致创建文件夹的数据库操作丢失或者时序错乱
修复方案
修正后的完整代码如下:
@Inject URepository uRepository; @POST @javax.ws.rs.Path("/add") @Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN}) @Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN }) public Uni<Response> addUser(UBean userIN,@HeaderParam("userName") String addedBy) { // 异步操作全部通过链式调用串接 return createNewFolders(userIN.getUserName()) .flatMap(c -> { if (c == 1) { // flatMap展开Uni类型的返回值 return uRepository.addUser(userIN) .map(h -> Response.ok(h.longValue()).build()); } else { // 异常场景可自定义返回值 return Uni.createFrom().item(Response.status(Response.Status.BAD_REQUEST) .entity("创建文件夹失败").build()); } }); } // 补全返回值,将文件夹创建操作拼入主流程 public Uni<Integer> createNewFolders(String addedBy) { FBean f=new FBean(addedBy); return calladdFile(f) .replaceWith(1); } // 改为返回Uni,不使用void类型 public Uni<Integer> calladdFile(FBean fileIN) { return addFile(fileIN); } public Uni<Integer> addFile(FBean fileIN) { Object[] array = {fileIN.getName(), fileIN.getExt(), fileIN.getOwner(), fileIN.getFrom(), fileIN.Date(), fileIN.getType()}; List<Object> l = Arrays.asList(array); Tuple t = Tuple.tuple(l); return SqlClientHelper.inTransactionUni(client, tx -> { return tx.preparedQuery(sql) .execute(t) .map(pg -> pg.iterator().next().getInteger("id")); }); }
关键修改说明
- 用
flatMap替代transform处理返回Uni的回调,自动展开嵌套的Uni结构,避免出现Uni<Uni<T>>的嵌套类型 - 所有异步操作全部通过Uni链式调用串接,避免出现脱离主流程的异步操作,防止操作丢失或者时序错误
- Response对象放在Uni的最内层返回,由RESTEasy Reactive自动处理最外层Uni的序列化逻辑,不要把Uni直接塞到Response的body中
- 补全了
createNewFolders方法漏写的return语句,避免空指针异常
内容的提问来源于stack exchange,提问作者user3458271
相关产品推荐
相关产品推荐

