[CORDA-1297] Columns nullability (#3112)

JPA/Hibernate entities need to impose the correct NULL/NOT NULL constraints on the database - whatever these correct values actually are.
API change: net.corda.core.schemas.PersistentStateRef fields (index and txId) are now non-nullable. Rationale: The fields were always effectively non-nullable - values were set from non-nullable fields of other objects. The class is used in context of database table Primary Key of for other entities and a database already imposes those columns as non-nullable (even if JPA annotation nullable=false was absent).
This commit is contained in:
Maksymilian Pawlak 2018-05-25 18:03:24 +01:00 committed by szymonsztuka
parent 380ab22917
commit 7d69bc664a
34 changed files with 175 additions and 137 deletions

View File

@ -4339,21 +4339,19 @@ public class net.corda.core.schemas.PersistentState extends java.lang.Object imp
@Embeddable
public class net.corda.core.schemas.PersistentStateRef extends java.lang.Object implements java.io.Serializable
public <init>()
public <init>(String, Integer)
public <init>(String, int)
public <init>(net.corda.core.contracts.StateRef)
@Nullable
public final String component1()
@Nullable
public final Integer component2()
@NotNull
public final net.corda.core.schemas.PersistentStateRef copy(String, Integer)
public final String component1()
public final int component2()
@NotNull
public final net.corda.core.schemas.PersistentStateRef copy(String, int)
public boolean equals(Object)
@Nullable
public Integer getIndex()
@Nullable
public int getIndex()
@NotNull
public String getTxId()
public int hashCode()
public void setIndex(Integer)
public void setIndex(int)
public void setTxId(String)
public String toString()
##

View File

@ -54,7 +54,7 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers
/** [OwnableState] attributes */
/** X500Name of owner party **/
@Column(name = "owner_name")
@Column(name = "owner_name", nullable = true)
var owner: AbstractParty,
/** [FungibleAsset] attributes
@ -64,16 +64,16 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers
*/
/** Amount attributes */
@Column(name = "quantity")
@Column(name = "quantity", nullable = false)
var quantity: Long,
/** Issuer attributes */
/** X500Name of issuer party **/
@Column(name = "issuer_name")
@Column(name = "issuer_name", nullable = true)
var issuer: AbstractParty,
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE)
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false)
@Type(type = "corda-wrapper-binary")
var issuerRef: ByteArray
) : PersistentState()

View File

@ -78,11 +78,11 @@ class PersistentState(@EmbeddedId var stateRef: PersistentStateRef? = null) : St
*/
@Embeddable
data class PersistentStateRef(
@Column(name = "transaction_id", length = 64)
var txId: String? = null,
@Column(name = "transaction_id", length = 64, nullable = false)
var txId: String,
@Column(name = "output_index")
var index: Int? = null
@Column(name = "output_index", nullable = false)
var index: Int
) : Serializable {
constructor(stateRef: StateRef) : this(stateRef.txhash.bytes.toHexString(), stateRef.index)
}

View File

@ -96,6 +96,12 @@ Unreleased
* Node can be shut down abruptly by ``shutdown`` function in `CordaRPCOps` or gracefully (draining flows first) through ``gracefulShutdown`` command from shell.
* API change: ``net.corda.core.schemas.PersistentStateRef`` fields (index and txId) are now non-nullable.
The fields were always effectively non-nullable - values were set from non-nullable fields of other objects.
The class is used as database Primary Key columns of other entities and databases already impose those columns as non-nullable
(even if JPA annotation nullable=false was absent).
In case your Cordapps use this entity class to persist data in own custom tables as non Primary Key columns refer to :doc:`upgrade-notes` for upgrade instructions.
.. _changelog_v3.1:
Version 3.1
@ -118,6 +124,7 @@ Version 3.1
* Fixed node's behaviour on startup when there is no connectivity to network map. Node continues to work normally if it has
all the needed network data, waiting in the background for network map to become available.
.. _changelog_v3:
Version 3.0

View File

@ -33,6 +33,40 @@ UNRELEASED
<<< Fill this in >>>
* API change: ``net.corda.core.schemas.PersistentStateRef`` fields (``index`` and ``txId``) incorrectly marked as nullable are now non-nullable,
:doc:`changelog` contains the explanation.
H2 database upgrade action:
For Cordapps persisting custom entities with ``PersistentStateRef`` used as non Primary Key column, the backing table needs to be updated,
In SQL replace ``your_transaction_id``/``your_output_index`` column names with your custom names, if entity didn't used JPA ``@AttributeOverrides``
then default names are ``transaction_id`` and ``output_index``.
.. sourcecode:: sql
SELECT count(*) FROM [YOUR_PersistentState_TABLE_NAME] WHERE your_transaction_id IS NULL OR your_output_index IS NULL;
In case your table already contains rows with NULL columns, and the logic doesn't distinguish between NULL and an empty string,
all NULL column occurrences can be changed to an empty string:
.. sourcecode:: sql
UPDATE [YOUR_PersistentState_TABLE_NAME] SET your_transaction_id="" WHERE your_transaction_id IS NULL;
UPDATE [YOUR_PersistentState_TABLE_NAME] SET your_output_index="" WHERE your_output_index IS NULL;
If all rows have NON NULL ``transaction_ids`` and ``output_idx`` or you have assigned empty string values, then it's safe to update the table:
.. sourcecode:: sql
ALTER TABLE [YOUR_PersistentState_TABLE_NAME] ALTER COLUMN your_transaction_id SET NOT NULL;
ALTER TABLE [YOUR_PersistentState_TABLE_NAME] ALTER COLUMN your_output_index SET NOT NULL;
If the table already contains rows with NULL values, and the logic caters differently between NULL and an empty string,
and the logic has to be preserved you would need to create copy of ``PersistentStateRef`` class with different name and use the new class in your entity.
No action is needed for default node tables as ``PersistentStateRef`` is used as Primary Key only and the backing columns are automatically not nullable
or custom Cordapp entities using ``PersistentStateRef`` as Primary Key.
v3.0 to v3.1
------------

View File

@ -24,19 +24,19 @@ object CashSchemaV1 : MappedSchema(schemaFamily = CashSchema.javaClass, version
@Table(name = "contract_cash_states", indexes = [Index(name = "ccy_code_idx", columnList = "ccy_code"), Index(name = "pennies_idx", columnList = "pennies")])
class PersistentCashState(
/** X500Name of owner party **/
@Column(name = "owner_name")
@Column(name = "owner_name", nullable = true)
var owner: AbstractParty,
@Column(name = "pennies")
@Column(name = "pennies", nullable = false)
var pennies: Long,
@Column(name = "ccy_code", length = 3)
@Column(name = "ccy_code", length = 3, nullable = false)
var currency: String,
@Column(name = "issuer_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "issuer_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var issuerPartyHash: String,
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE)
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false)
@Type(type = "corda-wrapper-binary")
var issuerRef: ByteArray
) : PersistentState()

View File

@ -26,29 +26,29 @@ object CommercialPaperSchemaV1 : MappedSchema(schemaFamily = CommercialPaperSche
@Entity
@Table(name = "cp_states", indexes = [Index(name = "ccy_code_index", columnList = "ccy_code"), Index(name = "maturity_index", columnList = "maturity_instant"), Index(name = "face_value_index", columnList = "face_value")])
class PersistentCommercialPaperState(
@Column(name = "issuance_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "issuance_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var issuancePartyHash: String,
@Column(name = "issuance_ref")
@Column(name = "issuance_ref", nullable = false)
@Type(type = "corda-wrapper-binary")
var issuanceRef: ByteArray,
@Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var ownerHash: String,
@Column(name = "maturity_instant")
@Column(name = "maturity_instant", nullable = false)
var maturity: Instant,
@Column(name = "face_value")
@Column(name = "face_value", nullable = false)
var faceValue: Long,
@Column(name = "ccy_code", length = 3)
@Column(name = "ccy_code", length = 3, nullable = false)
var currency: String,
@Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var faceValueIssuerPartyHash: String,
@Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE)
@Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false)
@Type(type = "corda-wrapper-binary")
var faceValueIssuerRef: ByteArray
) : PersistentState()

View File

@ -244,7 +244,7 @@ class CommercialPaperTestsGeneric {
// MegaCorp will issue some commercial paper and Alice will buy it, using cash issued to her in the name
// of the dummy cash issuer.
val allIdentities = arrayOf(megaCorp.identity, miniCorp.identity, dummyCashIssuer.identity, dummyNotary.identity)
val allIdentities = arrayOf(megaCorp.identity, alice.identity, dummyCashIssuer.identity, dummyNotary.identity)
val notaryServices = MockServices(dummyNotary)
val issuerServices = MockServices(dummyCashIssuer, dummyNotary)
val (aliceDatabase, aliceServices) = makeTestDatabaseAndMockServices(

View File

@ -82,10 +82,11 @@ class CashTests {
LogHelper.setLevel(NodeVaultService::class)
megaCorpServices = MockServices(megaCorp)
miniCorpServices = MockServices(miniCorp)
val myself = TestIdentity(CordaX500Name("Me", "London", "GB"))
val databaseAndServices = makeTestDatabaseAndMockServices(
listOf("net.corda.finance.contracts.asset"),
makeTestIdentityService(megaCorp.identity, miniCorp.identity, dummyCashIssuer.identity, dummyNotary.identity),
TestIdentity(CordaX500Name("Me", "London", "GB"))
makeTestIdentityService(megaCorp.identity, miniCorp.identity, dummyCashIssuer.identity, dummyNotary.identity, myself.identity),
myself
)
database = databaseAndServices.first
ourServices = databaseAndServices.second

View File

@ -21,21 +21,21 @@ object CashSchema
*/
object SampleCashSchemaV1 : MappedSchema(schemaFamily = CashSchema.javaClass, version = 1, mappedTypes = listOf(PersistentCashState::class.java)) {
@Entity
@Table(name = "contract_cash_states", indexes = [Index(name = "ccy_code_idx", columnList = "ccy_code"), Index(name = "pennies_idx", columnList = "pennies")])
@Table(name = "contract_cash_states_v1", indexes = [Index(name = "ccy_code_idx", columnList = "ccy_code"), Index(name = "pennies_idx", columnList = "pennies")])
class PersistentCashState(
@Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var ownerHash: String,
@Column(name = "pennies")
@Column(name = "pennies", nullable = false)
var pennies: Long,
@Column(name = "ccy_code", length = 3)
@Column(name = "ccy_code", length = 3, nullable = false)
var currency: String,
@Column(name = "issuer_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "issuer_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var issuerPartyHash: String,
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE)
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false)
@Type(type = "corda-wrapper-binary")
var issuerRef: ByteArray
) : PersistentState()

View File

@ -15,7 +15,7 @@ object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, ve
@Table(name = "cash_states_v2", indexes = [Index(name = "ccy_code_idx2", columnList = "ccy_code")])
class PersistentCashState(
/** product type */
@Column(name = "ccy_code", length = 3)
@Column(name = "ccy_code", length = 3, nullable = false)
var currency: String,
participants: Set<AbstractParty>,
owner: AbstractParty,
@ -25,7 +25,7 @@ object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, ve
) : CommonSchemaV1.FungibleState(participants.toMutableSet(), owner, quantity, issuerParty, issuerRef.bytes) {
@ElementCollection
@Column(name = "participants")
@Column(name = "participants", nullable = true)
@CollectionTable(name = "cash_states_v2_participants", joinColumns = [JoinColumn(name = "output_index", referencedColumnName = "output_index"), JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")])
override var participants: MutableSet<AbstractParty>? = null
}

View File

@ -26,20 +26,20 @@ object SampleCashSchemaV3 : MappedSchema(schemaFamily = CashSchema.javaClass, ve
var participants: MutableSet<AbstractParty>? = null,
/** X500Name of owner party **/
@Column(name = "owner_name")
@Column(name = "owner_name", nullable = true)
var owner: AbstractParty,
@Column(name = "pennies")
@Column(name = "pennies", nullable = false)
var pennies: Long,
@Column(name = "ccy_code", length = 3)
@Column(name = "ccy_code", length = 3, nullable = false)
var currency: String,
/** X500Name of issuer party **/
@Column(name = "issuer_name")
@Column(name = "issuer_name", nullable = true)
var issuer: AbstractParty,
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE)
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false)
@Type(type = "corda-wrapper-binary")
var issuerRef: ByteArray
) : PersistentState()

View File

@ -24,29 +24,29 @@ object SampleCommercialPaperSchemaV1 : MappedSchema(schemaFamily = CommercialPap
@Entity
@Table(name = "cp_states", indexes = [Index(name = "ccy_code_index", columnList = "ccy_code"), Index(name = "maturity_index", columnList = "maturity_instant"), Index(name = "face_value_index", columnList = "face_value")])
class PersistentCommercialPaperState(
@Column(name = "issuance_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "issuance_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var issuancePartyHash: String,
@Column(name = "issuance_ref")
@Column(name = "issuance_ref", nullable = false)
@Type(type = "corda-wrapper-binary")
var issuanceRef: ByteArray,
@Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var ownerHash: String,
@Column(name = "maturity_instant")
@Column(name = "maturity_instant", nullable = false)
var maturity: Instant,
@Column(name = "face_value")
@Column(name = "face_value", nullable = false)
var faceValue: Long,
@Column(name = "ccy_code", length = 3)
@Column(name = "ccy_code", length = 3, nullable = false)
var currency: String,
@Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var faceValueIssuerPartyHash: String,
@Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE)
@Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false)
@Type(type = "corda-wrapper-binary")
var faceValueIssuerRef: ByteArray
) : PersistentState()

View File

@ -19,16 +19,16 @@ object SampleCommercialPaperSchemaV2 : MappedSchema(schemaFamily = CommercialPap
@Entity
@Table(name = "cp_states_v2", indexes = [Index(name = "ccy_code_index2", columnList = "ccy_code"), Index(name = "maturity_index2", columnList = "maturity_instant")])
class PersistentCommercialPaperState(
@Column(name = "maturity_instant")
@Column(name = "maturity_instant", nullable = false)
var maturity: Instant,
@Column(name = "ccy_code", length = 3)
@Column(name = "ccy_code", length = 3, nullable = false)
var currency: String,
@Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var faceValueIssuerPartyHash: String,
@Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE)
@Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false)
@Type(type = "corda-wrapper-binary")
var faceValueIssuerRef: ByteArray,

View File

@ -40,10 +40,10 @@ object MessageSchemaV1 : MappedSchema(
@Entity
@Table(name = "messages")
class PersistentMessage(
@Column(name = "message_by")
@Column(name = "message_by", nullable = false)
var by: String,
@Column(name = "message_value")
@Column(name = "message_value", nullable = false)
var value: String
) : PersistentState()
}

View File

@ -25,25 +25,25 @@ object NodeInfoSchemaV1 : MappedSchema(
class PersistentNodeInfo(
@Id
@GeneratedValue
@Column(name = "node_info_id")
@Column(name = "node_info_id", nullable = false)
var id: Int,
@Column(name = "node_info_hash", length = 64)
@Column(name = "node_info_hash", length = 64, nullable = false)
val hash: String,
@Column(name = "addresses")
@Column(name = "addresses", nullable = false)
@OneToMany(cascade = [(CascadeType.ALL)], orphanRemoval = true)
@JoinColumn(name = "node_info_id", foreignKey = ForeignKey(name = "FK__info_hosts__infos"))
val addresses: List<DBHostAndPort>,
@Column(name = "legal_identities_certs")
@Column(name = "legal_identities_certs", nullable = false)
@ManyToMany(cascade = [(CascadeType.ALL)])
@JoinTable(name = "node_link_nodeinfo_party",
joinColumns = [(JoinColumn(name = "node_info_id", foreignKey = ForeignKey(name = "FK__link_nodeinfo_party__infos")))],
inverseJoinColumns = [(JoinColumn(name = "party_name", foreignKey = ForeignKey(name = "FK__link_ni_p__info_p_cert")))])
val legalIdentitiesAndCerts: List<DBPartyAndCertificate>,
@Column(name = "platform_version")
@Column(name = "platform_version", nullable = false)
val platformVersion: Int,
/**
@ -51,7 +51,7 @@ object NodeInfoSchemaV1 : MappedSchema(
* Not expected to be sequential, but later versions of the registration must have higher values
* Similar to the serial number on DNS records.
*/
@Column(name = "serial")
@Column(name = "serial", nullable = false)
val serial: Long
) : Serializable {
fun toNodeInfo(): NodeInfo {
@ -69,7 +69,7 @@ object NodeInfoSchemaV1 : MappedSchema(
data class DBHostAndPort(
@Id
@GeneratedValue
@Column(name = "hosts_id")
@Column(name = "hosts_id", nullable = false)
var id: Int,
val host: String? = null,
val port: Int? = null
@ -95,11 +95,11 @@ object NodeInfoSchemaV1 : MappedSchema(
@Column(name = "party_name", nullable = false)
val name: String,
@Column(name = "owning_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "owning_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
val owningKeyHash: String,
@Lob
@Column(name = "party_cert_binary")
@Column(name = "party_cert_binary", nullable = false)
val partyCertBinary: ByteArray,
val isMain: Boolean,

View File

@ -132,7 +132,7 @@ class NodeSchedulerService(private val clock: CordaClock,
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}scheduled_states")
class PersistentScheduledState(
@EmbeddedId
var output: PersistentStateRef = PersistentStateRef(),
var output: PersistentStateRef,
@Column(name = "scheduled_at", nullable = false)
var scheduledAt: Instant = Instant.now()

View File

@ -18,8 +18,8 @@ class PersistentScheduledFlowRepository(val database: CordaPersistence) : Schedu
}
private fun toPersistentEntity(key: StateRef, value: ScheduledStateRef): NodeSchedulerService.PersistentScheduledState {
return NodeSchedulerService.PersistentScheduledState().apply {
output = PersistentStateRef(key.txhash.toString(), key.index)
val output = PersistentStateRef(key.txhash.toString(), key.index)
return NodeSchedulerService.PersistentScheduledState(output).apply {
scheduledAt = value.scheduledAt
}
}

View File

@ -78,11 +78,11 @@ class PersistentIdentityService(override val trustRoot: X509Certificate,
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}identities")
class PersistentIdentity(
@Id
@Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var publicKeyHash: String = "",
@Lob
@Column(name = "identity_value")
@Column(name = "identity_value", nullable = false)
var identity: ByteArray = EMPTY_BYTE_ARRAY
) : Serializable
@ -90,10 +90,10 @@ class PersistentIdentityService(override val trustRoot: X509Certificate,
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}named_identities")
class PersistentIdentityNames(
@Id
@Column(name = "name", length = 128)
@Column(name = "name", length = 128, nullable = false)
var name: String = "",
@Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var publicKeyHash: String = ""
) : Serializable

View File

@ -34,14 +34,14 @@ class PersistentKeyManagementService(val identityService: IdentityService,
class PersistentKey(
@Id
@Column(name = "public_key_hash", length = MAX_HASH_HEX_SIZE)
@Column(name = "public_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false)
var publicKeyHash: String,
@Lob
@Column(name = "public_key")
@Column(name = "public_key", nullable = false)
var publicKey: ByteArray = EMPTY_BYTE_ARRAY,
@Lob
@Column(name = "private_key")
@Column(name = "private_key", nullable = false)
var privateKey: ByteArray = EMPTY_BYTE_ARRAY
) : Serializable {
constructor(publicKey: PublicKey, privateKey: PrivateKey)

View File

@ -86,16 +86,16 @@ class P2PMessageDeduplicator(private val database: CordaPersistence) {
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}message_ids")
class ProcessedMessage(
@Id
@Column(name = "message_id", length = 64)
@Column(name = "message_id", length = 64, nullable = false)
var id: String = "",
@Column(name = "insertion_time")
@Column(name = "insertion_time", nullable = false)
var insertionTime: Instant = Instant.now(),
@Column(name = "sender", length = 64)
@Column(name = "sender", length = 64, nullable = true)
var hash: String? = "",
@Column(name = "sequence_number")
@Column(name = "sequence_number", nullable = true)
var seqNo: Long? = null
) : Serializable

View File

@ -176,14 +176,14 @@ class P2PMessagingClient(val config: NodeConfiguration,
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}message_retry")
class RetryMessage(
@Id
@Column(name = "message_id", length = 64)
@Column(name = "message_id", length = 64, nullable = false)
var key: Long = 0,
@Lob
@Column
@Column(nullable = false)
var message: ByteArray = EMPTY_BYTE_ARRAY,
@Lob
@Column
@Column(nullable = false)
var recipients: ByteArray = EMPTY_BYTE_ARRAY
) : Serializable

View File

@ -28,11 +28,11 @@ class DBCheckpointStorage : CheckpointStorage {
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}checkpoints")
class DBCheckpoint(
@Id
@Column(name = "checkpoint_id", length = 64)
@Column(name = "checkpoint_id", length = 64, nullable = false)
var checkpointId: String = "",
@Lob
@Column(name = "checkpoint_value")
@Column(name = "checkpoint_value", nullable = false)
var checkpoint: ByteArray = EMPTY_BYTE_ARRAY
) : Serializable

View File

@ -29,10 +29,10 @@ class DBTransactionMappingStorage : StateMachineRecordedTransactionMappingStorag
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}transaction_mappings")
class DBTransactionMapping(
@Id
@Column(name = "tx_id", length = 64)
@Column(name = "tx_id", length = 64, nullable = false)
var txId: String = "",
@Column(name = "state_machine_run_id", length = 36)
@Column(name = "state_machine_run_id", length = 36, nullable = false)
var stateMachineRunId: String = ""
) : Serializable

View File

@ -34,11 +34,11 @@ class DBTransactionStorage(cacheSizeBytes: Long) : WritableTransactionStorage, S
@Table(name = "${NODE_DATABASE_PREFIX}transactions")
class DBTransaction(
@Id
@Column(name = "tx_id", length = 64)
@Column(name = "tx_id", length = 64, nullable = false)
var txId: String = "",
@Lob
@Column(name = "transaction_value")
@Column(name = "transaction_value", nullable = false)
var transaction: ByteArray = EMPTY_BYTE_ARRAY
) : Serializable

View File

@ -79,24 +79,24 @@ class NodeAttachmentService(
@Table(name = "${NODE_DATABASE_PREFIX}attachments", indexes = [Index(name = "att_id_idx", columnList = "att_id")])
class DBAttachment(
@Id
@Column(name = "att_id")
@Column(name = "att_id", nullable = false)
var attId: String,
@Column(name = "content")
@Column(name = "content", nullable = false)
@Lob
var content: ByteArray,
@Column(name = "insertion_date", nullable = false, updatable = false)
var insertionDate: Instant = Instant.now(),
@Column(name = "uploader", updatable = false)
@Column(name = "uploader", updatable = false, nullable = true)
var uploader: String? = null,
@Column(name = "filename", updatable = false)
@Column(name = "filename", updatable = false, nullable = true)
var filename: String? = null,
@ElementCollection
@Column(name = "contract_class_name")
@Column(name = "contract_class_name", nullable = false)
@CollectionTable(name = "node_attchments_contracts", joinColumns = [(JoinColumn(name = "att_id", referencedColumnName = "att_id"))],
foreignKey = ForeignKey(name = "FK__ctr_class__attachments"))
var contractClassNames: List<ContractClassName>? = null

View File

@ -30,10 +30,10 @@ class NodePropertiesPersistentStore(readPhysicalNodeId: () -> String, persistenc
@Table(name = "${NODE_DATABASE_PREFIX}properties")
class DBNodeProperty(
@Id
@Column(name = "property_key")
@Column(name = "property_key", nullable = false)
val key: String = "",
@Column(name = "property_value")
@Column(name = "property_value", nullable = true)
var value: String? = ""
) : Serializable
}

View File

@ -106,8 +106,7 @@ class BFTNonValidatingNotaryService(
fromPersistentEntity = {
//TODO null check will become obsolete after making DB/JPA columns not nullable
val txId = it.id.txId
?: throw IllegalStateException("DB returned null SecureHash transactionId")
val index = it.id.index ?: throw IllegalStateException("DB returned null SecureHash index")
val index = it.id.index
Pair(
StateRef(txhash = SecureHash.parse(txId), index = index),
SecureHash.parse(it.consumingTxHash)

View File

@ -37,7 +37,7 @@ class PersistentUniquenessProvider(val clock: Clock) : UniquenessProvider, Singl
@EmbeddedId
val id: PersistentStateRef,
@Column(name = "consuming_transaction_id")
@Column(name = "consuming_transaction_id", nullable = false)
val consumingTxHash: String
) : Serializable
@ -47,19 +47,20 @@ class PersistentUniquenessProvider(val clock: Clock) : UniquenessProvider, Singl
class Request(
@Id
@GeneratedValue
@Column(nullable = true)
val id: Int? = null,
@Column(name = "consuming_transaction_id")
@Column(name = "consuming_transaction_id", nullable = false)
val consumingTxHash: String,
@Column(name = "requesting_party_name")
@Column(name = "requesting_party_name", nullable = false)
var partyName: String,
@Lob
@Column(name = "request_signature")
@Column(name = "request_signature", nullable = false)
val requestSignature: ByteArray,
@Column(name = "request_timestamp")
@Column(name = "request_timestamp", nullable = false)
var requestDate: Instant
) : Serializable
@ -81,8 +82,7 @@ class PersistentUniquenessProvider(val clock: Clock) : UniquenessProvider, Singl
fromPersistentEntity = {
//TODO null check will become obsolete after making DB/JPA columns not nullable
val txId = it.id.txId
?: throw IllegalStateException("DB returned null SecureHash transactionId")
val index = it.id.index ?: throw IllegalStateException("DB returned null SecureHash index")
val index = it.id.index
Pair(
StateRef(txhash = SecureHash.parse(txId), index = index),
SecureHash.parse(it.consumingTxHash)

View File

@ -65,8 +65,7 @@ class RaftUniquenessProvider(
toPersistentEntityKey = { PersistentStateRef(it) },
fromPersistentEntity = {
val txId = it.id.txId
?: throw IllegalStateException("DB returned null SecureHash transactionId")
val index = it.id.index ?: throw IllegalStateException("DB returned null SecureHash index")
val index = it.id.index
Pair(
StateRef(txhash = SecureHash.parse(txId), index = index),
Pair(it.index, SecureHash.parse(it.value) as SecureHash))
@ -91,9 +90,9 @@ class RaftUniquenessProvider(
class CommittedState(
@EmbeddedId
val id: PersistentStateRef,
@Column(name = "consuming_transaction_id")
@Column(name = "consuming_transaction_id", nullable = false)
var value: String = "",
@Column(name = "raft_log_index")
@Column(name = "raft_log_index", nullable = false)
var index: Long = 0
) : Serializable

View File

@ -18,11 +18,11 @@ class ContractUpgradeServiceImpl : ContractUpgradeService, SingletonSerializeAsT
@Table(name = "${NODE_DATABASE_PREFIX}contract_upgrades")
class DBContractUpgrade(
@Id
@Column(name = "state_ref", length = 96)
@Column(name = "state_ref", length = 96, nullable = false)
var stateRef: String = "",
/** refers to the UpgradedContract class name*/
@Column(name = "contract_class_name")
@Column(name = "contract_class_name", nullable = false)
var upgradedContractClassName: String = ""
) : Serializable

View File

@ -34,19 +34,19 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
// TODO: create a distinct table to hold serialized state data (once DBTransactionStore is encrypted)
/** refers to the X500Name of the notary a state is attached to */
@Column(name = "notary_name")
@Column(name = "notary_name", nullable = false)
var notary: Party,
/** references a concrete ContractState that is [QueryableState] and has a [MappedSchema] */
@Column(name = "contract_state_class_name")
@Column(name = "contract_state_class_name", nullable = false)
var contractStateClassName: String,
/** state lifecycle: unconsumed, consumed */
@Column(name = "state_status")
@Column(name = "state_status", nullable = false)
var stateStatus: Vault.StateStatus,
/** refers to timestamp recorded upon entering UNCONSUMED state */
@Column(name = "recorded_timestamp")
@Column(name = "recorded_timestamp", nullable = false)
var recordedTime: Instant,
/** refers to timestamp recorded upon entering CONSUMED state */
@ -81,7 +81,7 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
/**
* Represents a [LinearState] [UniqueIdentifier]
*/
@Column(name = "external_id")
@Column(name = "external_id", nullable = true)
var externalId: String?,
@Column(name = "uuid", nullable = false)
@ -104,13 +104,13 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
@CollectionTable(name = "vault_fungible_states_parts",
joinColumns = [(JoinColumn(name = "output_index", referencedColumnName = "output_index")), (JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))],
foreignKey = ForeignKey(name = "FK__fung_st_parts__fung_st"))
@Column(name = "participants")
@Column(name = "participants", nullable = true)
var participants: MutableSet<AbstractParty>? = null,
/** [OwnableState] attributes */
/** X500Name of owner party **/
@Column(name = "owner_name")
@Column(name = "owner_name", nullable = true)
var owner: AbstractParty,
/** [FungibleAsset] attributes
@ -120,16 +120,16 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
*/
/** Amount attributes */
@Column(name = "quantity")
@Column(name = "quantity", nullable = false)
var quantity: Long,
/** Issuer attributes */
/** X500Name of issuer party **/
@Column(name = "issuer_name")
@Column(name = "issuer_name", nullable = true)
var issuer: AbstractParty,
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE)
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false)
@Type(type = "corda-wrapper-binary")
var issuerRef: ByteArray
) : PersistentState() {
@ -146,13 +146,13 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
class VaultTxnNote(
@Id
@GeneratedValue
@Column(name = "seq_no")
@Column(name = "seq_no", nullable = false)
var seqNo: Int,
@Column(name = "transaction_id", length = 64)
@Column(name = "transaction_id", length = 64, nullable = false)
var txId: String,
@Column(name = "note")
@Column(name = "note", nullable = false)
var note: String
) : Serializable {
constructor(txId: String, note: String) : this(0, txId, note)

View File

@ -31,7 +31,7 @@ object DummyLinearStateSchemaV1 : MappedSchema(schemaFamily = DummyLinearStateSc
/**
* UniqueIdentifier
*/
@Column(name = "external_id")
@Column(name = "external_id", nullable = true)
var externalId: String?,
@Column(name = "uuid", nullable = false)
@ -41,16 +41,16 @@ object DummyLinearStateSchemaV1 : MappedSchema(schemaFamily = DummyLinearStateSc
/**
* Dummy attributes
*/
@Column(name = "linear_string")
@Column(name = "linear_string", nullable = false)
var linearString: String,
@Column(name = "linear_number")
@Column(name = "linear_number", nullable = false)
var linearNumber: Long,
@Column(name = "linear_timestamp")
@Column(name = "linear_timestamp", nullable = false)
var linearTimestamp: Instant,
@Column(name = "linear_boolean")
@Column(name = "linear_boolean", nullable = false)
var linearBoolean: Boolean
) : PersistentState()
}

View File

@ -21,13 +21,13 @@ object DummyLinearStateSchemaV2 : MappedSchema(schemaFamily = DummyLinearStateSc
@CollectionTable(name = "dummy_linear_states_v2_parts", joinColumns = [(JoinColumn(name = "output_index", referencedColumnName = "output_index")), (JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))])
override var participants: MutableSet<AbstractParty>? = null,
@Column(name = "linear_string") var linearString: String,
@Column(name = "linear_string", nullable = false) var linearString: String,
@Column(name = "linear_number") var linearNumber: Long,
@Column(name = "linear_number", nullable = false) var linearNumber: Long,
@Column(name = "linear_timestamp") var linearTimestamp: java.time.Instant,
@Column(name = "linear_timestamp", nullable = false) var linearTimestamp: java.time.Instant,
@Column(name = "linear_boolean") var linearBoolean: Boolean,
@Column(name = "linear_boolean", nullable = false) var linearBoolean: Boolean,
@Transient
val uid: UniqueIdentifier