如何使用VaultCustomQuery查询父状态嵌套集合字段及解决子实体查询报错
如何用VaultCustomQuery查询父状态嵌套集合内的字段
你遇到的「AttachmentEntity is not a subtype of PersistentState」错误,核心原因是VaultCustomQueryCriteria只能直接作用于顶层的PersistentState实体,而你的AttachmentEntity是嵌套在父状态里的子实体,不属于顶层PersistentState类型,所以直接用它的字段构建条件会报错。下面给你一步步的解决方案:
第一步:确保Schema正确映射嵌套集合关系
首先要在你的MappedSchema里,正确定义父状态实体和子实体的关联关系,用JPA注解标记一对多/多对一的映射,确保子实体有外键关联父实体。举个Kotlin的示例:
object ContractSchemaV1 : MappedSchema( schemaFamily = ContractState::class.java, version = 1, mappedTypes = listOf(ContractStateEntity::class.java, AttachmentEntity::class.java) ) { @Entity @Table(name = "contract_states") class ContractStateEntity( @Column(name = "contract_id") val contractId: String, // 父状态的其他字段... // 标记一对多关系,关联子实体 @OneToMany(mappedBy = "contract", cascade = [CascadeType.ALL], fetch = FetchType.LAZY) val attachments: List<AttachmentEntity> = emptyList() ) : PersistentState() { // JPA要求的无参构造函数 constructor() : this("") } @Entity @Table(name = "attachments") class AttachmentEntity( @Column(name = "attachment_hash") val attachmentHash: String, @Column(name = "upload_date") val uploadDate: Instant, @Column(name = "file_type") val fileType: String, // 标记多对一关系,外键关联父实体 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "contract_state_id") val contract: ContractStateEntity? = null ) { // JPA要求的无参构造函数 constructor() : this("", Instant.now(), "", null) } }
第二步:用Join关联父实体和子实体构建查询
既然不能直接用子实体作为查询主体,我们需要通过join方法把父实体(PersistentState类型)和子实体关联起来,然后基于子实体的字段过滤父状态。示例代码如下:
// 先构建子实体字段的查询条件 val attachmentDateCriteria = builder { AttachmentEntity::uploadDate.equal(Instant.parse("2024-01-01T00:00:00Z")) } // 关联父实体和子实体,再组合子实体的条件 val queryCriteria = QueryCriteria.VaultCustomQueryCriteria( builder { // 建立父实体和子实体的关联 ContractStateEntity::class.java join AttachmentEntity::class.java on AttachmentEntity::contract } ).and(attachmentDateCriteria) // 执行查询,返回符合条件的父状态 val matchingStates = serviceHub.vaultService.queryBy<ContractState>(queryCriteria).states
关键注意点
- 子实体必须被包含在MappedSchema的
mappedTypes列表中,否则框架无法识别它的映射关系 - 关联时要确保
on后面的字段是子实体中指向父实体的属性(比如上面的AttachmentEntity::contract) - 如果需要多个子实体条件,可以继续用
.and()或.or()组合多个子条件
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

