@PrimaryKey
Designates a property as (part of) the primary key. Every @DbEntity class must have at least one @PrimaryKey property — annotate two or more to form a composite key.
Signature
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
annotation class PrimaryKey(
val autoGenerate: Boolean = false
)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
autoGenerate |
Boolean |
false |
When true, declares the column as INTEGER PRIMARY KEY AUTOINCREMENT. SQLite assigns the id on insert. The property type must be Long or Int. |
Usage
The most common pattern. Pass id = 0 on insert — SQLite assigns the real id.
@DbEntity(tableName = "tasks")
data class Task(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val title: String
)
// Insert — id is assigned by SQLite
taskRepo.insert(Task(title = "Buy groceries"))
// Read back with the generated id
val tasks = taskRepo.findAll() // tasks[0].id == 1L (or next autoincrement)
Use when the entity has a natural unique identifier (UUID, slug, barcode, etc.).
When you manage the id externally (e.g. from a server response).
Annotate two or more properties to form a composite primary key — the usual case is a junction/join table, like an assignment of a user to a task.
@DbEntity(tableName = "assignments")
data class Assignment(
@PrimaryKey val taskId: Long,
@PrimaryKey val userId: Long,
val assignedAt: String = ""
)
Kiln generates a AssignmentKey(taskId, userId) data class and uses it as the
ID type everywhere a single-key entity would use its PK's own type directly:
val key = AssignmentKey(taskId = 1L, userId = 2L)
assignmentRepo.insert(Assignment(taskId = 1L, userId = 2L))
val assignment = assignmentRepo.findById(key)
assignmentRepo.delete(key)
update(entity) is unaffected — it still takes the whole entity and matches
on every @PrimaryKey property internally, same as a single key.
In a junction table the key columns are usually also foreign keys, so you can
add @Relation to each and get the FK helpers alongside the composite key:
@DbEntity(tableName = "assignments")
data class Assignment(
@PrimaryKey @Relation val taskId: Long,
@PrimaryKey @Relation val userId: Long,
val assignedAt: String = ""
)
// Generated from @Relation on the key columns:
assignmentRepo.findByTask(taskId = 1L) // List<Assignment>
assignmentRepo.findByUser(userId = 2L) // List<Assignment>
assignmentRepo.deleteByTask(taskId = 1L) // drop every assignment for a task
Constraints
autoGenerate requires Long or Int
Setting autoGenerate = true on a property of any other type produces a compile-time error:
autoGenerate is not available on a composite key
autoGenerate only makes sense for a single integer PK. Setting it on any
property once a class has two or more @PrimaryKey properties is a
compile-time error:
@Relation works on @PrimaryKey properties
A key column can also carry @Relation (shown in the composite-key example
above). This covers junction tables — where each half of the composite key is a
foreign key — and shared-primary-key one-to-one tables, where a single PK is also
an FK to the parent.