You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Mutiny、Quarkus响应式SQL实现无阻塞递归家族树查询

问题描述

我有一个Person表,结构如下:

Person表字段类型
personIdINT
NameVarChar
fatherIdINT -- 引用同表(Person)的personId
MotherIdINT -- 引用同表(Person)的personId
其他字段其他详情

我需要实现一个异步方法来返回家族树,功能和以下同步实现一致,同时要避免阻塞IO异常,使用Mutiny和Quarkus响应式SQL来完成。

旧同步实现

我的POJO类:

public class FamilyTree {
    Person person;
    FamilyTree fatherFamily;
    FamilyTree motherFamily;
    
    public FamilyTree(Person person, FamilyTree father, FamilyTree mother) {
        this.person = person;
        this.fatherFamily = father;
        this.motherFamily = mother;
    }
    
    public static FamilyTree buildFamilyTree(int personId) {
        Person person = PersonRepository.GetPersonById(personId);
        FamilyTree fatherTree = (person.getFatherId() == null || person.getFatherId().isEmpty()) 
            ? null : buildFamilyTree(person.getFatherId());
        FamilyTree motherTree = (person.getMotherId() == null || person.getMotherId().isEmpty()) 
            ? null : buildFamilyTree(person.getMotherId());
        return new FamilyTree(person, fatherTree, motherTree);
    }
}

待实现的响应式类

我已经写了部分代码,需要完成getFamilyTree方法的实现:

@ApplicationScoped
public class FamilyTreeRepository {

    @Inject
    OraclePool client;
    
    public Uni<Person> getPersonById(int personId) {
        String sql = "select * from person where personId=?";
        Tuple tuple = Tuple.of(personId);
        return client.preparedQuery(sql).execute(tuple)
            .onItem().transform(Rowset::iterator)
            .onItem().transform(iterator -> iterator.hasNext() ? Person.convertPerson(iterator.next()) : null);
    }
    
    public Uni<FamilyTree> getFamilyTree(int personId) {
        Uni<Person> person = getPersonById(personId);
        // 需要完成这里的实现
        return familyTree;
    }
}

实现方案

要实现异步非阻塞的家族树构建,需利用Mutiny的Uni API处理异步依赖,核心逻辑是异步获取当前Person、并行递归获取父/母系家族树,最后合并结果构造实例。完整的getFamilyTree方法实现如下:

public Uni<FamilyTree> getFamilyTree(int personId) {
    // 异步获取当前Person
    return getPersonById(personId)
        // 仅当Person存在时继续处理
        .onItem().ifNotNull().transformToUni(person -> {
            // 异步获取父系家族树:ID存在则递归调用,否则返回null的Uni
            Uni<FamilyTree> fatherTreeUni = Optional.ofNullable(person.getFatherId())
                .filter(id -> !id.isEmpty())
                .map(this::getFamilyTree)
                .orElseGet(() -> Uni.createFrom().nullItem());
            
            // 异步获取母系家族树:逻辑同父系
            Uni<FamilyTree> motherTreeUni = Optional.ofNullable(person.getMotherId())
                .filter(id -> !id.isEmpty())
                .map(this::getFamilyTree)
                .orElseGet(() -> Uni.createFrom().nullItem());
            
            // 并行合并父/母系家族树的结果,构造FamilyTree
            return Uni.combine().all().unis(fatherTreeUni, motherTreeUni)
                .asTuple()
                .onItem().transform(tuple -> new FamilyTree(person, tuple.getItem1(), tuple.getItem2()));
        })
        // 若Person不存在,返回null的Uni
        .onItem().ifNull().continueWith(null);
}

关键细节说明

  • 非阻塞递归:递归调用getFamilyTree返回的是Uni<FamilyTree>,不会阻塞线程,完全符合Quarkus响应式非阻塞要求
  • 并行异步处理:用Uni.combine()并行获取父/母系家族树,相比串行调用能有效提升查询性能
  • 空值安全处理:通过Optional和Uni.createFrom().nullItem()优雅处理父/母ID不存在的场景,避免空指针异常
  • 流式响应式风格:全程使用Mutiny链式API,保持代码简洁且无阻塞IO操作

内容的提问来源于stack exchange,提问作者luiza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:30:57