如何用Mutiny、Quarkus响应式SQL实现无阻塞递归家族树查询
问题描述
我有一个Person表,结构如下:
| Person表字段 | 类型 |
|---|---|
| personId | INT |
| Name | VarChar |
| fatherId | INT -- 引用同表(Person)的personId |
| MotherId | INT -- 引用同表(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
相关产品推荐
相关产品推荐

