Primary Keys
This chapter will introduce the concept and usage of primary key types in Kronos.
Declare a primary key
Use @PrimaryKey on one KPojo property. With no generation flag, the field maps to PrimaryKeyType.DEFAULT. Without @PrimaryKey, the field maps to PrimaryKeyType.NOT.
The examples on this page use these imports:
model
import com.kotlinorm.annotations.PrimaryKey
import com.kotlinorm.annotations.Table
import com.kotlinorm.interfaces.KPojo
import com.kotlinorm.orm.insert.insert
@Table("tb_user")
data class User(
@PrimaryKey(identity = true)
var id: Int? = null,
var username: String? = null
) : KPojoThe generated field metadata is:
metadata
id.primaryKey -> PrimaryKeyType.IDENTITY
id.nullable -> false
username.primaryKey -> PrimaryKeyType.NOTUse one generation flag on a primary key field: identity, uuid, snowflake, or custom.
PrimaryKeyType reference
| Type | Annotation shape | Insert behavior | DDL behavior |
|---|---|---|---|
NOT | No @PrimaryKey | Normal column. | Not a primary key. |
DEFAULT | @PrimaryKey | Uses the value already on the KPojo. | Primary key column. |
IDENTITY | @PrimaryKey(identity = true) | Omits the key column when the key value is null. | Database identity/autoincrement primary key. |
UUID | @PrimaryKey(uuid = true) | Writes UUIDGenerator.nextId() before insert. | Primary key column. |
SNOWFLAKE | @PrimaryKey(snowflake = true) | Writes SnowflakeIdGenerator.nextId() before insert. | Primary key column. |
CUSTOM | @PrimaryKey(custom = true) | Writes customIdGenerator?.nextId() before insert. | Primary key column. |
DEFAULT Manual primary key
Use @PrimaryKey without flags when your application or database supplies the key value.
kotlin
@Table("tb_region")
data class Region(
@PrimaryKey
var code: String? = null,
var name: String? = null
) : KPojo
Region(code = "CN", name = "China").insert().build()Mysql
INSERT INTO `tb_region` (`code`, `name`) VALUES (:code, :name)params
code -> "CN"
name -> "China"Table creation treats the field as a normal primary key column.
DDL
`code` VARCHAR(255) NOT NULL PRIMARY KEYIDENTITY Database-generated key
Use identity = true for an Int or Long key generated by the database.
kotlin
@Table("tb_user")
data class IdentityUser(
@PrimaryKey(identity = true)
var id: Int? = null,
var username: String? = null
) : KPojo
IdentityUser(username = "Ada").insert().build()When id is null, Kronos removes the identity field from the insert column list.
Mysql
INSERT INTO `tb_user` (`username`) VALUES (:username)params
username -> "Ada"The MySQL table column renders as:
DDL
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENTIf you provide an identity value yourself, Kronos keeps the key column in the INSERT. Use
📚Last Insert IDwhen an insert should read the database-generated value.
UUID UUID string key
Use uuid = true for a String key. Kronos calls UUIDGenerator.nextId() before building the insert SQL.
kotlin
@Table("tb_uuid_user")
data class UuidUser(
@PrimaryKey(uuid = true)
var id: String? = null,
var username: String? = null
) : KPojo
UuidUser(username = "Ada").insert().build()Mysql
INSERT INTO `tb_uuid_user` (`id`, `username`) VALUES (:id, :username)params
id -> "550e8400-e29b-41d4-a716-446655440000"
username -> "Ada"Table creation still renders a normal primary key column.
DDL
`id` VARCHAR(255) NOT NULL PRIMARY KEYSNOWFLAKE Snowflake key
Use snowflake = true for a Long key generated in the application process.
kotlin
@Table("tb_order")
data class OrderRecord(
@PrimaryKey(snowflake = true)
var id: Long? = null,
var status: String? = null
) : KPojo
OrderRecord(status = "created").insert().build()Mysql
INSERT INTO `tb_order` (`id`, `status`) VALUES (:id, :status)params
id -> 1912549819912192000
status -> "created"Configure node identifiers before inserts when multiple application nodes generate Snowflake IDs.
config
import com.kotlinorm.beans.generator.SnowflakeIdGenerator
fun configureSnowflakeIds() {
SnowflakeIdGenerator.datacenterId = 1
SnowflakeIdGenerator.workerId = 1
}datacenterId and workerId accept values from 0 to 31.
CUSTOM Custom generator key
Use custom = true when the key value should come from your own KIdGenerator.
generator
import com.kotlinorm.beans.generator.customIdGenerator
import com.kotlinorm.interfaces.KIdGenerator
object TicketIdGenerator : KIdGenerator<String> {
override fun nextId(): String = "ticket-${System.currentTimeMillis()}"
}
fun configureTicketIds() {
customIdGenerator = TicketIdGenerator
}model
@Table("tb_ticket")
data class Ticket(
@PrimaryKey(custom = true)
var id: String? = null,
var title: String? = null
) : KPojo
Ticket(title = "Login issue").insert().build()Mysql
INSERT INTO `tb_ticket` (`id`, `title`) VALUES (:id, :title)params
id -> "ticket-1912549819912"
title -> "Login issue"Set
customIdGeneratorbefore inserting acustomprimary key. If it is not set, the generated key parameter isnull.
Global primary-key strategy
The recommended mapping is to put @PrimaryKey on the key property. Use Kronos.primaryKeyStrategy only for unannotated models that share the same key field name.
config
import com.kotlinorm.Kronos
import com.kotlinorm.beans.config.KronosCommonStrategy
import com.kotlinorm.beans.dsl.Field
import com.kotlinorm.enums.PrimaryKeyType
fun configurePrimaryKeyStrategy() {
Kronos.primaryKeyStrategy = KronosCommonStrategy(
enabled = true,
field = Field("id", "id", primaryKey = PrimaryKeyType.IDENTITY)
)
}model
@Table("tb_audit_log")
data class AuditLog(
var id: Int? = null,
var message: String? = null
) : KPojoFor table creation and visible field metadata, prefer the property annotation:
recommended
@PrimaryKey(identity = true)
var id: Int? = null