逻辑删除
本章描述 mutation API 中的逻辑删除行为。
声明逻辑删除列
在标记删除状态的 KPojo 字段上使用 @LogicDelete。该注解默认启用。
User.kt
import com.kotlinorm.annotations.Default
import com.kotlinorm.annotations.LogicDelete
import com.kotlinorm.annotations.PrimaryKey
import com.kotlinorm.interfaces.KPojo
data class User(
@PrimaryKey(identity = true)
var id: Int? = null,
var name: String? = null,
@LogicDelete
@Default("0") // @Default("false") for Postgres
var deleted: Boolean? = null
) : KPojo应用中多个表使用同一个逻辑删除字段时,可以配置全局策略,并在需要启用的 KPojo 中保留该字段。
global config
import com.kotlinorm.Kronos
import com.kotlinorm.beans.config.KronosCommonStrategy
import com.kotlinorm.beans.dsl.Field
Kronos.logicDeleteStrategy = KronosCommonStrategy(enabled = true, field = Field("deleted"))删除会写入删除标记
启用逻辑删除后,delete().execute() 生成写入删除标记的 UPDATE。生成条件也会排除已经删除的行。
kotlin
User(id = 1)
.delete()
.by { it.id }
.execute()Mysql
UPDATE `user`
SET `deleted` = :deletedNew
WHERE `id` = :id
AND `deleted` = 0params
id = 1
deletedNew = 1当前删除需要生成物理 DELETE 时,调用 .logic(false)。
kotlin
User(id = 1)
.delete()
.logic(false)
.by { it.id }
.execute()Mysql
DELETE
FROM `user`
WHERE `id` = :id查询和更新会排除已删除行
对启用逻辑删除的 KPojo,select 和 update 会追加活动行条件。
kotlin
User()
.select { [it.id, it.name] }
.toMapList()
User(id = 1)
.update()
.set { it.name = "Kronos" }
.by { it.id }
.execute()select
SELECT `id`, `name`
FROM `user`
WHERE `deleted` = 0update
UPDATE `user`
SET `name` = :nameNew
WHERE `id` = :id
AND `deleted` = 0插入和 upsert 会维护标记
insert 会把逻辑删除字段初始化为活动值。按匹配字段执行 upsert 时,如果匹配到已逻辑删除的记录,Kronos 会更新这条记录并把逻辑删除字段恢复为活动值。策略启用时,onConflict() upsert 也会把该字段加入插入列,并在冲突更新时写回活动值。
kotlin
User(name = "Kronos")
.insert()
.execute()Mysql
INSERT INTO `user` (`name`, `deleted`)
VALUES (:name, :deleted)params
name = "Kronos"
deleted = 0kotlin
User(id = 1, name = "Kronos")
.upsert { it.name }
.on { it.id }
.execute()update
UPDATE `user`
SET `name` = :nameNew,
`deleted` = :deletedNew
WHERE `id` = :idDataGuard 边界
逻辑删除会把 delete 转成 update。没有用户条件时,生成语句仍可能命中全部活动行。
kotlin
User()
.delete()
.execute()Mysql
UPDATE `user`
SET `deleted` = :deletedNew
WHERE `deleted` = 0需要拒绝全表写入时,启用 📚DataGuard。条件 API 见 📚删除 和 📚更新。