corda - Corda - 查询 QueryableState 子表
问题描述
背景
我无法在示例 Corda 应用程序中查询子数据,演示如何使用QueryableState
.
以供参考:
- https://github.com/corda/samples-kotlin/tree/master/Features/queryableState-carinsurance
- https://www.corda.net/blog/persisting-corda-states-in-custom-database-tables-using-queryablestate/
汽车保险示例演示了如何设置:
PersistentInsurance
和之间的一对一关系PersistentVehicle
PersistentInsurance
和之间的一对多关系PersistentClaim
问题
汽车保险样本没有展示的是如何查询该数据。构建 Vault 查询PersistentInsurance
相当简单,因为我们可以使用它VaultCustomQueryCriteria
来构建基于 的属性的自定义查询表达式PersistentInsurance
,但是对于层次结构中的子表来说并非如此。这是因为PersistentInsurance
extends PersistentState
,而PersistentVehicle
和PersistentClaim
don't 。
对于 Reference,其底层类型层次结构PersistentState
如下:
StatePersistable
> DirectStatePersistable
>PersistentState
interface StatePersistable
interface DirectStatePersistable : StatePersistable {
val stateRef: PersistentStateRef?
}
class PersistentState(@EmbeddedId override var stateRef: PersistentStateRef? = null) : DirectStatePersistable
data class PersistentStateRef(
@Suppress("MagicNumber") // column width
@Column(name = "transaction_id", length = 144, nullable = false)
var txId: String,
@Column(name = "output_index", nullable = false)
var index: Int
) : Serializable {
constructor(stateRef: StateRef) : this(stateRef.txhash.toString(), stateRef.index)
}
回到汽车保险样本,我们不能使用VaultCustomQueryCriteria
forPersistentVehicle
或PersistentClaim
asVaultCustomQueryCriteria::expression
对 有一个通用约束StatePersistable
:
data class VaultCustomQueryCriteria<L : StatePersistable>(
val expression: CriteriaExpression<L, Boolean>,
...
) : CommonQueryCriteria() { ... }
我试过的
当您使用这些类中的任何属性创建 a 时StatePersistable
,实现PersistentVehicle
和/或PersistentClaim
导致以下错误:VaultCustomQueryCriteria
net.corda.core.node.services.VaultQueryException:解析错误:无法在此 ManagedType [...$PersistentClaim] 上找到具有给定名称 [stateRef] 的属性
在完成事务时执行DirectStatePersistable
或PersistentState
打开PersistentVehicle
和/或PersistentClaim
导致内部错误。流挂起并最终超时。由于代码隐藏在底层 Corda 服务的内部实现中,我无法准确确定错误发生的位置。
什么有效(容量有限)
我知道我们可以执行自定义 SQL 查询;例如:
val sqlQuery = buildString {
appendln("SELECT TRANSACTION_ID, OUTPUT_INDEX")
appendln("FROM CLAIM_DETAIL")
appendln("WHERE claimNumber = '123'")
}
val stateRefs = serviceHub.jdbcSession().executeCaseInsensitiveQuery(sqlQuery).map {
val txId = SecureHash.parse(it.getString("TRANSACTION_ID")
val index = it.getInt("OUTPUT_INDEX")
StateRef(txId, index)
}.toList().toBlocking().first()
VaultQueryCriteria(stateRefs = stateRefs)
不用说,与以下相比,这很可怕:
VaultCustomQueryCriteria(PersistentClaim::claimNumber.equal("123"))
至于为什么它以有限的容量工作,这对于节点内部的查询很有效,它可以访问服务中心,但不能通过 RPC 工作,因为无法访问jdbcSession
.
那么,关于我们如何提高子表的查询能力的任何想法(如果可能的话)?
解决方案
@Matthew Layton 我已将您的担忧提交给工程团队。团队对此进行了调查。
要解决/修复此问题,需要进行大量平台更改。
暂时我建议您使用本机查询进行管理。我们计划优先考虑这个问题。我会及时通知你。
推荐阅读
- mysql - 如何加入两个表并动态进行 Pivot
- django - 传递正确的 urls.py 模式
- python - 翻转numpy数组中的行
- java - java.net.URLEncoder 用 '+' 字符替换空格
- perl - 不能在没有包或对象引用的情况下调用方法“文件名”
- git - 用于从其他程序(例如 Git、PowerShell 或命令行)打开文件列表的单行命令
- asp.net-core - ASP.NET CORE RAZOR PAGES - 重载方法
- excel - EXCEL:对多行求和
- c++ - C++ 中的函子和 lambda
- omnet++ - Omnet++ 问题:对抽象 L3Address SlectedNodes[] 的字段使用标准容器类;// 将使用 std::vector?