问题
I have a one-to-many relationship where I am trying to add a list of object/class in my state. i.e
I have a contract state that has a list of attachments List<Attachment>, where Attachmentis just a class with fields like
attachmentHash, uploadedDate, fileType
I wanted to query with something in the child but I get syntax error
"AttachmentEntity is not a subtype of PersistentState"QueryCriteria.VaultCustomQueryCriteria( builder { (ContractSchemaV1.AttachmentEntity::uploadDate).equal(givenDate) }))I let AttachmentEntity be a subclass of
PersistentStateand the node started up with the errororg.hibernate.AnnotationException: net.corda.core.schemas.PersistentStateRef must not have @Id properties when used as an @EmbeddedId: project.schemas.ContractSchemaV1$AttachmentEntity.stateRef
Seems like I'm doing something wrong, whats the best way to represent a collection of data classes in the state and translate that in a schema? Or is this already the correct way, but there's no way to query the nested collection using VaultCustomQuery?
The example entity below.
object ContractSchema
object ContractSchemaV1 : MappedSchema(schemaFamily = ContractSchema.javaClass, version = 1,
mappedTypes = listOf(ContractEntity::class.java, AttachmentEntity:class.java)) {
@Entity
@Table(name = "contracts")
class ContractEntity(
@Column(name = "issued_date")
var issuedDate: Instant,
@Column(name = "linear_id")
var linearId: String,
@OneToMany(fetch = FetchType.LAZY, cascade = arrayOf(CascadeType.PERSIST))
@JoinColumns(
JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"),
JoinColumn(name = "output_index", referencedColumnName = "output_index"))
var attachments: MutableSet<AttachmentEntity> = emptyList(),
) : PersistentState()
@Entity
@Table(name = "attachments")
class AttachmentEntity (
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false)
var id: Long? = null,
@Column(name = "attachment_hash", nullable = false)
var attachmentHash: String? = null,
@Column(name = "attachment_name", nullable = false)
var attachmentName: String? = null,
@Column(name = "upload_date", nullable = true)
var uploadDate: Instant? = null)
}
回答1:
Your schema definition is correct (and you can see another example here: Querying nested collections in LinearState states).
However, querying nested collections is not supported by VaultCustomQueryCriteria. You have to do direct JDBC queries to query attributes of the nested collections.
Here is an example of a direct JDBC query in Corda:
@Test
fun `test calling an arbitrary JDBC native query`() {
val nativeQuery = "SELECT v.transaction_id, v.output_index FROM vault_states v WHERE v.state_status = 0"
database.transaction {
val jdbcSession = services.jdbcSession()
val prepStatement = jdbcSession.prepareStatement(nativeQuery)
val rs = prepStatement.executeQuery()
var count = 0
while (rs.next()) {
val stateRef = StateRef(SecureHash.parse(rs.getString(1)), rs.getInt(2))
Assert.assertTrue(cashStates.map { it.ref }.contains(stateRef))
count++
}
Assert.assertEquals(cashStates.count(), count)
}
}
来源:https://stackoverflow.com/questions/50207831/how-to-query-on-a-field-in-nested-collection-of-a-parent-state-using-vaultcustom