ENT-2848 remove need for generated IDs on some frequently used tables (#4446)

* Working version

* api-current.txt change to remove diff due to inheritance hierarchy change.

* api-current.txt change to remove warnings of abstract methods in new interfaces.

* Fix indent
This commit is contained in:
Rick Parker 2018-12-20 13:06:21 +00:00 committed by GitHub
parent af75a05502
commit 3efbad34cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 40 deletions

View File

@ -4398,6 +4398,14 @@ public static class net.corda.core.schemas.CommonSchemaV1$LinearState extends ne
public void setParticipants(java.util.Set<net.corda.core.identity.AbstractParty>) public void setParticipants(java.util.Set<net.corda.core.identity.AbstractParty>)
public void setUuid(java.util.UUID) public void setUuid(java.util.UUID)
## ##
public interface net.corda.core.schemas.DirectStatePersistable extends net.corda.core.schemas.StatePersistable
@Nullable
public abstract net.corda.core.schemas.PersistentStateRef getStateRef()
##
public interface net.corda.core.schemas.IndirectStatePersistable extends net.corda.core.schemas.StatePersistable
@NotNull
public abstract T getCompositeKey()
##
public class net.corda.core.schemas.MappedSchema extends java.lang.Object public class net.corda.core.schemas.MappedSchema extends java.lang.Object
public <init>(Class<?>, int, Iterable<? extends Class<?>>) public <init>(Class<?>, int, Iterable<? extends Class<?>>)
@NotNull @NotNull
@ -4410,7 +4418,7 @@ public class net.corda.core.schemas.MappedSchema extends java.lang.Object
## ##
@MappedSuperclass @MappedSuperclass
@CordaSerializable @CordaSerializable
public class net.corda.core.schemas.PersistentState extends java.lang.Object implements net.corda.core.schemas.StatePersistable public class net.corda.core.schemas.PersistentState extends java.lang.Object implements net.corda.core.schemas.DirectStatePersistable
public <init>() public <init>()
public <init>(net.corda.core.schemas.PersistentStateRef) public <init>(net.corda.core.schemas.PersistentStateRef)
@Nullable @Nullable

View File

@ -82,7 +82,7 @@ open class MappedSchema(schemaFamily: Class<*>,
@KeepForDJVM @KeepForDJVM
@MappedSuperclass @MappedSuperclass
@CordaSerializable @CordaSerializable
class PersistentState(@EmbeddedId var stateRef: PersistentStateRef? = null) : StatePersistable class PersistentState(@EmbeddedId override var stateRef: PersistentStateRef? = null) : DirectStatePersistable
/** /**
* Embedded [StateRef] representation used in state mapping. * Embedded [StateRef] representation used in state mapping.
@ -106,6 +106,21 @@ data class PersistentStateRef(
@KeepForDJVM @KeepForDJVM
interface StatePersistable interface StatePersistable
/**
* Marker interface to denote a persistable Corda state entity that exposes the transaction id and index as composite key called [stateRef].
*/
interface DirectStatePersistable : StatePersistable {
val stateRef: PersistentStateRef?
}
/**
* Marker interface to denote a persistable Corda state entity that exposes the transaction id and index as a nested composite key called [compositeKey]
* that is itself a [DirectStatePersistable]. i.e. exposes a [stateRef].
*/
interface IndirectStatePersistable<T : DirectStatePersistable> : StatePersistable {
val compositeKey: T
}
object MappedSchemaValidator { object MappedSchemaValidator {
fun fieldsFromOtherMappedSchema(schema: MappedSchema) : List<SchemaCrossReferenceReport> = fun fieldsFromOtherMappedSchema(schema: MappedSchema) : List<SchemaCrossReferenceReport> =
schema.mappedTypes.map { entity -> schema.mappedTypes.map { entity ->

View File

@ -16,6 +16,7 @@ import net.corda.core.node.services.vault.LikenessOperator.*
import net.corda.core.node.services.vault.NullOperator.IS_NULL import net.corda.core.node.services.vault.NullOperator.IS_NULL
import net.corda.core.node.services.vault.NullOperator.NOT_NULL import net.corda.core.node.services.vault.NullOperator.NOT_NULL
import net.corda.core.node.services.vault.QueryCriteria.CommonQueryCriteria import net.corda.core.node.services.vault.QueryCriteria.CommonQueryCriteria
import net.corda.core.schemas.IndirectStatePersistable
import net.corda.core.schemas.PersistentState import net.corda.core.schemas.PersistentState
import net.corda.core.schemas.PersistentStateRef import net.corda.core.schemas.PersistentStateRef
import net.corda.core.schemas.StatePersistable import net.corda.core.schemas.StatePersistable
@ -460,7 +461,7 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
} }
// Add the join and participants predicates. // Add the join and participants predicates.
val statePartyJoin = criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"), entityRoot.get<VaultSchemaV1.PersistentParty>("stateRef")) val statePartyJoin = criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"), entityRoot.get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))
val participantsPredicate = criteriaBuilder.and(entityRoot.get<VaultSchemaV1.PersistentParty>("x500Name").`in`(participants)) val participantsPredicate = criteriaBuilder.and(entityRoot.get<VaultSchemaV1.PersistentParty>("x500Name").`in`(participants))
predicateSet.add(statePartyJoin) predicateSet.add(statePartyJoin)
predicateSet.add(participantsPredicate) predicateSet.add(participantsPredicate)
@ -512,7 +513,7 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
} }
// Add the join and participants predicates. // Add the join and participants predicates.
val statePartyJoin = criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"), entityRoot.get<VaultSchemaV1.PersistentParty>("stateRef")) val statePartyJoin = criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"), entityRoot.get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))
val participantsPredicate = criteriaBuilder.and(entityRoot.get<VaultSchemaV1.PersistentParty>("x500Name").`in`(participants)) val participantsPredicate = criteriaBuilder.and(entityRoot.get<VaultSchemaV1.PersistentParty>("x500Name").`in`(participants))
predicateSet.add(statePartyJoin) predicateSet.add(statePartyJoin)
predicateSet.add(participantsPredicate) predicateSet.add(participantsPredicate)
@ -536,7 +537,11 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
entityRoot entityRoot
} }
val joinPredicate = criteriaBuilder.equal(vaultStates.get<PersistentStateRef>("stateRef"), entityRoot.get<PersistentStateRef>("stateRef")) val joinPredicate = if(IndirectStatePersistable::class.java.isAssignableFrom(entityRoot.javaType)) {
criteriaBuilder.equal(vaultStates.get<PersistentStateRef>("stateRef"), entityRoot.get<IndirectStatePersistable<*>>("compositeKey").get<PersistentStateRef>("stateRef"))
} else {
criteriaBuilder.equal(vaultStates.get<PersistentStateRef>("stateRef"), entityRoot.get<PersistentStateRef>("stateRef"))
}
predicateSet.add(joinPredicate) predicateSet.add(joinPredicate)
// resolve general criteria expressions // resolve general criteria expressions

View File

@ -136,8 +136,8 @@ class NodeVaultService(
val constraintInfo = Vault.ConstraintInfo(stateAndRef.value.state.constraint) val constraintInfo = Vault.ConstraintInfo(stateAndRef.value.state.constraint)
// Save a row for each party in the state_party table. // Save a row for each party in the state_party table.
// TODO: Perhaps these can be stored in a batch? // TODO: Perhaps these can be stored in a batch?
stateOnly.participants.forEach { participant -> stateOnly.participants.groupBy { it.owningKey }.forEach { participants ->
val persistentParty = VaultSchemaV1.PersistentParty(persistentStateRef, participant) val persistentParty = VaultSchemaV1.PersistentParty(persistentStateRef, participants.value.first())
session.save(persistentParty) session.save(persistentParty)
} }
val stateToAdd = VaultSchemaV1.VaultStates( val stateToAdd = VaultSchemaV1.VaultStates(

View File

@ -8,14 +8,12 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.node.services.MAX_CONSTRAINT_DATA_SIZE import net.corda.core.node.services.MAX_CONSTRAINT_DATA_SIZE
import net.corda.core.node.services.Vault import net.corda.core.node.services.Vault
import net.corda.core.schemas.MappedSchema import net.corda.core.schemas.*
import net.corda.core.schemas.PersistentState
import net.corda.core.schemas.PersistentStateRef
import net.corda.core.schemas.StatePersistable
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import org.hibernate.annotations.Immutable import org.hibernate.annotations.Immutable
import org.hibernate.annotations.Type import org.hibernate.annotations.Type
import java.io.Serializable
import java.time.Instant import java.time.Instant
import java.util.* import java.util.*
import javax.persistence.* import javax.persistence.*
@ -161,47 +159,35 @@ object VaultSchemaV1 : MappedSchema(
constructor(txId: String, note: String) : this(0, txId, note) constructor(txId: String, note: String) : this(0, txId, note)
} }
@Embeddable
@Immutable
data class PersistentStateRefAndKey(/* Foreign key. */ @Embedded override var stateRef: PersistentStateRef?, @Column(name = "public_key_hash", nullable = false) var publicKeyHash: String?) : DirectStatePersistable, Serializable {
constructor() : this(null, null)
}
@Entity @Entity
@Table(name = "state_party", indexes = [Index(name = "state_party_idx", columnList = "public_key_hash")]) @Table(name = "state_party", indexes = [Index(name = "state_party_idx", columnList = "public_key_hash")])
class PersistentParty( class PersistentParty(
@Id @EmbeddedId
@GeneratedValue override val compositeKey: PersistentStateRefAndKey,
@Column(name = "id", unique = true, nullable = false)
val id: Long?,
// Foreign key.
@Column(name = "state_ref")
val stateRef: PersistentStateRef,
@Column(name = "public_key_hash", nullable = false)
val publicKeyHash: String,
@Column(name = "x500_name", nullable = true) @Column(name = "x500_name", nullable = true)
var x500Name: AbstractParty? = null var x500Name: AbstractParty? = null
) : StatePersistable { ) : IndirectStatePersistable<PersistentStateRefAndKey> {
constructor(stateRef: PersistentStateRef, abstractParty: AbstractParty) constructor(stateRef: PersistentStateRef, abstractParty: AbstractParty)
: this(null, stateRef, abstractParty.owningKey.toStringShort(), abstractParty) : this(PersistentStateRefAndKey(stateRef, abstractParty.owningKey.toStringShort()), abstractParty)
} }
@Entity @Entity
@Immutable @Immutable
@Table(name = "v_pkey_hash_ex_id_map") @Table(name = "v_pkey_hash_ex_id_map")
class StateToExternalId( class StateToExternalId(
@Id @EmbeddedId
@GeneratedValue override val compositeKey: PersistentStateRefAndKey,
@Column(name = "id", unique = true, nullable = false)
val id: Long,
// Foreign key.
@Column(name = "state_ref")
val stateRef: PersistentStateRef,
@Column(name = "public_key_hash")
val publicKeyHash: String,
@Column(name = "external_id") @Column(name = "external_id")
@Type(type = "uuid-char") @Type(type = "uuid-char")
val externalId: UUID val externalId: UUID
) : StatePersistable ) : IndirectStatePersistable<PersistentStateRefAndKey>
} }

View File

@ -6,9 +6,6 @@
<createTable tableName="state_party"> <createTable tableName="state_party">
<column name="output_index" type="INT"/> <column name="output_index" type="INT"/>
<column name="transaction_id" type="NVARCHAR(64)"/> <column name="transaction_id" type="NVARCHAR(64)"/>
<column name="id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="public_key_hash" type="NVARCHAR(255)"> <column name="public_key_hash" type="NVARCHAR(255)">
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
@ -33,7 +30,6 @@
</createIndex> </createIndex>
<createView viewName="v_pkey_hash_ex_id_map"> <createView viewName="v_pkey_hash_ex_id_map">
select select
state_party.id,
state_party.public_key_hash, state_party.public_key_hash,
state_party.transaction_id, state_party.transaction_id,
state_party.output_index, state_party.output_index,