diff --git a/.ci/api-current.txt b/.ci/api-current.txt index f3eee165fa..493a31b91a 100644 --- a/.ci/api-current.txt +++ b/.ci/api-current.txt @@ -2613,22 +2613,22 @@ public final class net.corda.core.schemas.CommonSchemaV1 extends net.corda.core. @org.jetbrains.annotations.NotNull public final net.corda.core.identity.AbstractParty getIssuer() @org.jetbrains.annotations.NotNull public final byte[] getIssuerRef() @org.jetbrains.annotations.NotNull public final net.corda.core.identity.AbstractParty getOwner() - @org.jetbrains.annotations.Nullable public final Set getParticipants() + @org.jetbrains.annotations.Nullable public Set getParticipants() public final long getQuantity() public final void setIssuer(net.corda.core.identity.AbstractParty) public final void setIssuerRef(byte[]) public final void setOwner(net.corda.core.identity.AbstractParty) - public final void setParticipants(Set) + public void setParticipants(Set) public final void setQuantity(long) ## @javax.persistence.MappedSuperclass @net.corda.core.serialization.CordaSerializable public static class net.corda.core.schemas.CommonSchemaV1$LinearState extends net.corda.core.schemas.PersistentState public (Set, String, UUID) public (net.corda.core.contracts.UniqueIdentifier, Set) @org.jetbrains.annotations.Nullable public final String getExternalId() - @org.jetbrains.annotations.Nullable public final Set getParticipants() + @org.jetbrains.annotations.Nullable public Set getParticipants() @org.jetbrains.annotations.NotNull public final UUID getUuid() public final void setExternalId(String) - public final void setParticipants(Set) + public void setParticipants(Set) public final void setUuid(UUID) ## public class net.corda.core.schemas.MappedSchema extends java.lang.Object diff --git a/core/src/main/kotlin/net/corda/core/internal/schemas/NodeInfoSchema.kt b/core/src/main/kotlin/net/corda/core/internal/schemas/NodeInfoSchema.kt index 9cb84357b5..6e35a631c4 100644 --- a/core/src/main/kotlin/net/corda/core/internal/schemas/NodeInfoSchema.kt +++ b/core/src/main/kotlin/net/corda/core/internal/schemas/NodeInfoSchema.kt @@ -32,14 +32,14 @@ object NodeInfoSchemaV1 : MappedSchema( @Column(name = "addresses") @OneToMany(cascade = arrayOf(CascadeType.ALL), orphanRemoval = true) - @JoinColumn(name = "node_info_id") + @JoinColumn(name = "node_info_id", foreignKey = ForeignKey(name = "FK__info_hosts__infos")) val addresses: List, @Column(name = "legal_identities_certs") @ManyToMany(cascade = arrayOf(CascadeType.ALL)) @JoinTable(name = "node_link_nodeinfo_party", - joinColumns = arrayOf(JoinColumn(name = "node_info_id")), - inverseJoinColumns = arrayOf(JoinColumn(name = "party_name"))) + joinColumns = arrayOf(JoinColumn(name = "node_info_id", foreignKey = ForeignKey(name = "FK__link_nodeinfo_party__infos"))), + inverseJoinColumns = arrayOf(JoinColumn(name = "party_name", foreignKey = ForeignKey(name = "FK__link_ni_p__info_p_cert")))) val legalIdentitiesAndCerts: List, @Column(name = "platform_version") diff --git a/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt b/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt index a630a7b8e3..e7770667d3 100644 --- a/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt +++ b/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt @@ -5,8 +5,8 @@ import net.corda.core.identity.AbstractParty import org.hibernate.annotations.Type import java.util.* import javax.persistence.Column -import javax.persistence.ElementCollection import javax.persistence.MappedSuperclass +import javax.persistence.Transient /** * JPA representation of the common schema entities @@ -23,9 +23,8 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers /** [ContractState] attributes */ /** X500Name of participant parties **/ - @ElementCollection - @Column(name = "participants") - var participants: MutableSet? = null, + @Transient + open var participants: MutableSet? = null, /** * Represents a [LinearState] [UniqueIdentifier] @@ -34,6 +33,7 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers var externalId: String?, @Column(name = "uuid", nullable = false) + @Type(type = "uuid-char") var uuid: UUID ) : PersistentState() { @@ -48,9 +48,8 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers /** [ContractState] attributes */ /** X500Name of participant parties **/ - @ElementCollection - @Column(name = "participants") - var participants: MutableSet? = null, + @Transient + open var participants: MutableSet? = null, /** [OwnableState] attributes */ diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index da570bd9ee..ac9093745b 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -6,6 +6,9 @@ from the previous milestone release. UNRELEASED ---------- +* JPA Mapping annotations for States extending ``CommonSchemaV1.LinearState`` and ``CommonSchemaV1.FungibleState`` on the + `participants` collection need to be moved to the actual class. This allows to properly specify the unique table name per a collection. + See: DummyDealStateSchemaV1.PersistentDummyDealState * X.509 certificates now have an extension that specifies the Corda role the certificate is used for, and the role hierarchy is now enforced in the validation code. See ``net.corda.core.internal.CertRole`` for the current implementation diff --git a/docs/source/upgrade-notes.rst b/docs/source/upgrade-notes.rst index baa2328b4e..da66072fbe 100644 --- a/docs/source/upgrade-notes.rst +++ b/docs/source/upgrade-notes.rst @@ -31,6 +31,26 @@ We also strongly recommend cross referencing with the :doc:`changelog` to confir UNRELEASED ---------- +* For existing contract ORM schemas that extend from `CommonSchemaV1.LinearState` or `CommonSchemaV1.FungibleState`, + you will need to explicitly map the `participants` collection to a database table. Previously this mapping was done in the + superclass, but that makes it impossible to properly configure the table name. + The required change is to add the ``override var participants: MutableSet? = null`` field to your class, and + add JPA mappings. For ex., see this example: + +.. sourcecode:: kotlin + + @Entity + @Table(name = "cash_states_v2", + indexes = arrayOf(Index(name = "ccy_code_idx2", columnList = "ccy_code"))) + class PersistentCashState( + + @ElementCollection + @Column(name = "participants") + @CollectionTable(name="cash_states_v2_participants", joinColumns = arrayOf( + JoinColumn(name = "output_index", referencedColumnName = "output_index"), + JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) + override var participants: MutableSet? = null, + Testing ~~~~~~~ diff --git a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt index 8b548f89ce..bea02485cf 100644 --- a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt +++ b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt @@ -4,10 +4,7 @@ import net.corda.core.identity.AbstractParty import net.corda.core.schemas.CommonSchemaV1 import net.corda.core.schemas.MappedSchema import net.corda.core.utilities.OpaqueBytes -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.Index -import javax.persistence.Table +import javax.persistence.* /** * Second version of a cash contract ORM schema that extends the common @@ -19,6 +16,14 @@ object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, ve @Table(name = "cash_states_v2", indexes = arrayOf(Index(name = "ccy_code_idx2", columnList = "ccy_code"))) class PersistentCashState( + + @ElementCollection + @Column(name = "participants") + @CollectionTable(name="cash_states_v2_participants", joinColumns = arrayOf( + JoinColumn(name = "output_index", referencedColumnName = "output_index"), + JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) + override var participants: MutableSet? = null, + /** product type */ @Column(name = "ccy_code", length = 3) var currency: String, diff --git a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt index 2c7882c048..fb646d123b 100644 --- a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt +++ b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt @@ -8,10 +8,7 @@ import net.corda.core.utilities.MAX_HASH_HEX_SIZE import net.corda.core.utilities.OpaqueBytes import org.hibernate.annotations.Type import java.time.Instant -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.Index -import javax.persistence.Table +import javax.persistence.* /** * Second version of a cash contract ORM schema that extends the common @@ -24,6 +21,14 @@ object SampleCommercialPaperSchemaV2 : MappedSchema(schemaFamily = CommercialPap indexes = arrayOf(Index(name = "ccy_code_index2", columnList = "ccy_code"), Index(name = "maturity_index2", columnList = "maturity_instant"))) class PersistentCommercialPaperState( + + @ElementCollection + @Column(name = "participants") + @CollectionTable(name="cp_states_v2_participants", joinColumns = arrayOf( + JoinColumn(name = "output_index", referencedColumnName = "output_index"), + JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) + override var participants: MutableSet? = null, + @Column(name = "maturity_instant") var maturity: Instant, diff --git a/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt b/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt index 78d5a3ac60..a86585bc87 100644 --- a/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt +++ b/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt @@ -77,7 +77,8 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio @CollectionTable(name = "vault_linear_states_parts", joinColumns = arrayOf( JoinColumn(name = "output_index", referencedColumnName = "output_index"), - JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) + JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")), + foreignKey = ForeignKey(name = "FK__lin_stat_parts__lin_stat")) @Column(name = "participants") var participants: MutableSet? = null, // Reason for not using Set is described here: @@ -109,7 +110,8 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio @CollectionTable(name = "vault_fungible_states_parts", joinColumns = arrayOf( JoinColumn(name = "output_index", referencedColumnName = "output_index"), - JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) + JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")), + foreignKey = ForeignKey(name = "FK__fung_st_parts__fung_st")) @Column(name = "participants") var participants: MutableSet? = null, diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyDealContract.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyDealContract.kt index 453dac658c..1cd75a83b0 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyDealContract.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyDealContract.kt @@ -31,7 +31,7 @@ class DummyDealContract : Contract { override fun generateMappedObject(schema: MappedSchema): PersistentState { return when (schema) { is DummyDealStateSchemaV1 -> DummyDealStateSchemaV1.PersistentDummyDealState( - _participants = participants.toSet(), + participants = participants.toMutableSet(), uid = linearId ) else -> throw IllegalArgumentException("Unrecognised schema $schema") diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyDealStateSchemaV1.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyDealStateSchemaV1.kt index 493e4688a5..9ed95d29b7 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyDealStateSchemaV1.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyDealStateSchemaV1.kt @@ -4,9 +4,7 @@ import net.corda.core.contracts.UniqueIdentifier import net.corda.core.identity.AbstractParty import net.corda.core.schemas.CommonSchemaV1 import net.corda.core.schemas.MappedSchema -import javax.persistence.Entity -import javax.persistence.Table -import javax.persistence.Transient +import javax.persistence.* /** * An object used to fully qualify the [DummyDealStateSchema] family name (i.e. independent of version). @@ -22,11 +20,15 @@ object DummyDealStateSchemaV1 : MappedSchema(schemaFamily = DummyDealStateSchema @Table(name = "dummy_deal_states") class PersistentDummyDealState( /** parent attributes */ - @Transient - val _participants: Set, + @ElementCollection + @Column(name = "participants") + @CollectionTable(name = "dummy_deal_states_participants", joinColumns = arrayOf( + JoinColumn(name = "output_index", referencedColumnName = "output_index"), + JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) + override var participants: MutableSet? = null, @Transient val uid: UniqueIdentifier - ) : CommonSchemaV1.LinearState(uid, _participants) + ) : CommonSchemaV1.LinearState(uuid = uid.id, externalId = uid.externalId, participants = participants) } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearContract.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearContract.kt index 0a2a962084..359e602180 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearContract.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearContract.kt @@ -49,7 +49,7 @@ class DummyLinearContract : Contract { linearBoolean = linearBoolean ) is DummyLinearStateSchemaV2 -> DummyLinearStateSchemaV2.PersistentDummyLinearState( - _participants = participants.toSet(), + participants = participants.toMutableSet(), uid = linearId, linearString = linearString, linearNumber = linearNumber, diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt index aa649337ff..d2ff099848 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt @@ -4,6 +4,7 @@ import net.corda.core.contracts.ContractState import net.corda.core.identity.AbstractParty import net.corda.core.schemas.MappedSchema import net.corda.core.schemas.PersistentState +import org.hibernate.annotations.Type import java.time.Instant import java.util.* import javax.persistence.* @@ -36,6 +37,7 @@ object DummyLinearStateSchemaV1 : MappedSchema(schemaFamily = DummyLinearStateSc var externalId: String?, @Column(name = "uuid", nullable = false) + @Type(type = "uuid-char") var uuid: UUID, /** diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt index 224d6fed87..6a25167c71 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt @@ -4,9 +4,7 @@ import net.corda.core.contracts.UniqueIdentifier import net.corda.core.identity.AbstractParty import net.corda.core.schemas.CommonSchemaV1 import net.corda.core.schemas.MappedSchema -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.Table +import javax.persistence.* /** * Second version of a cash contract ORM schema that extends the common @@ -17,6 +15,14 @@ object DummyLinearStateSchemaV2 : MappedSchema(schemaFamily = DummyLinearStateSc @Entity @Table(name = "dummy_linear_states_v2") class PersistentDummyLinearState( + + @ElementCollection + @Column(name = "participants") + @CollectionTable(name = "dummy_linear_states_v2_participants", joinColumns = arrayOf( + JoinColumn(name = "output_index", referencedColumnName = "output_index"), + JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) + override var participants: MutableSet? = null, + @Column(name = "linear_string") var linearString: String, @Column(name = "linear_number") var linearNumber: Long, @@ -25,11 +31,7 @@ object DummyLinearStateSchemaV2 : MappedSchema(schemaFamily = DummyLinearStateSc @Column(name = "linear_boolean") var linearBoolean: Boolean, - /** parent attributes */ - @Transient - val _participants: Set, - @Transient val uid: UniqueIdentifier - ) : CommonSchemaV1.LinearState(uid, _participants) + ) : CommonSchemaV1.LinearState(uuid = uid.id, externalId = uid.externalId, participants = participants) }