Corda V3自定义FungibleState Schema:基于父类瞬态属性对子类分组
解决Corda V3中基于父类瞬态属性分组自定义FungibleState的问题
我来帮你搞定这个分组需求~首先得明确一个关键前提:Corda的Vault数据库查询只能针对持久化到数据库的属性(也就是你自定义Schema里映射的那些列)。而父类的瞬态属性(标注了@Transient的)并没有存在数据库里,所以没法直接用SQL层面的分组来实现。咱们得换个思路,分两步走:先把目标状态查出来,再在内存里基于瞬态属性分组。
下面是具体的实现步骤:
1. 先确认父类瞬态属性的定义
首先得确保你要用来分组的父类属性确实是瞬态的(用@Transient标注),比如你的自定义FungibleState父类可能是这样的:
abstract class BaseCustomFungibleState : FungibleState<TokenType> { @Transient // 这就是我们要用来分组的瞬态属性,比如基于其他持久化属性推导出来的值 val groupingTransientProp: String get() = this.somePersistentProperty.split("-")[0] // 举个例子,从持久化属性拆分出分组键 }
2. 查询所有目标自定义状态
先用Vault Query把所有你需要的CustomState(也就是你扩展FungibleState的自定义状态)查出来,比如只查未消耗的状态:
// 构建查询条件,这里以查询未消耗状态为例 val queryCriteria = QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED) // 执行查询,提取出状态数据部分 val allCustomStates = serviceHub.vaultService.queryBy<CustomState>(queryCriteria) .states .map { it.state.data }
3. 在内存中基于瞬态属性分组
拿到所有状态数据后,直接用Kotlin的集合API做内存分组就行,非常方便:
// 按照父类的瞬态属性groupingTransientProp分组 val groupedStates = allCustomStates.groupBy { it.groupingTransientProp } // 遍历分组结果,做你需要的处理 groupedStates.forEach { (groupKey, statesInGroup) -> println("分组键:$groupKey,包含的状态数量:${statesInGroup.size}") // 这里可以对每个分组里的状态做进一步业务处理,比如汇总金额等 }
特殊情况:瞬态属性依赖外部数据
如果你的瞬态属性需要依赖其他状态或者外部服务的数据,那可以先把依赖数据预加载好,再进行分组:
// 先查询依赖的外部状态 val externalStates = serviceHub.vaultService.queryBy<ExternalReferenceState>(...) .states .map { it.state.data } // 把外部数据转成映射,方便快速查找 val externalDataMap = externalStates.associateBy { it.referenceId } // 分组时结合外部数据计算瞬态属性 val groupedStates = allCustomStates.groupBy { customState -> // 从外部映射中获取依赖数据,计算出分组用的瞬态值 externalDataMap[customState.externalRefId]?.groupKey ?: "默认分组" }
额外提示
如果你的状态数量特别大,内存分组可能会有性能问题,这时候建议考虑把瞬态属性转化为持久化属性——也就是在状态创建的时候,把瞬态属性的计算结果提前存到自定义Schema的列里,这样就能直接用Corda Vault Query的groupBy参数做数据库层面的分组,效率会高很多。毕竟在Corda V3里,Vault Query的groupBy只支持持久化的列哦。
内容的提问来源于stack exchange,提问作者Matthieu Merlyn
相关产品推荐
相关产品推荐

