android房间数据库KOTLIN中的级联删除

Posted

技术标签:

【中文标题】android房间数据库KOTLIN中的级联删除【英文标题】:cascade delete in android room database KOTLIN 【发布时间】:2022-01-05 02:22:54 【问题描述】:

*** 中有很多这样的问题,但大部分都不是关于房间数据库的,所以我不得不问一个新问题。

我有一个使用房间数据库的应用程序,它有近 4 个表并且这些表之间的关系很大,所以例如当我在用户列表片段中删除一个用户时,该用户删除(只有用户名和一些个人信息)但是用户的 TRANSACTIONS 和 LOANS 没有被删除。 有人告诉我必须使用 Cascade delete,但我没有找到太多相关信息。

我的用户类模型:

@Entity(tableName = "user_info")
data class UserInfo(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "user_id")
var userId: Long =0L,
@ColumnInfo(name = "full_name")
var fullName:String?,
@ColumnInfo(name= "account_id")
var accountId: String?,
@ColumnInfo(name = "mobile_number")
var mobileNumber:String?,
@ColumnInfo(name = "phone_number")
var phoneNumber:String?,
@ColumnInfo(name = "date_of_creation")
var dateOfCreation:String?,
@ColumnInfo(name = "address")
var address:String?,
)

交易模型类:

@Entity(tableName = "transactions")
data class Transactions(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "trans_id")
    var transId: Long = 0L,
    @ColumnInfo(name = "user_id")
    var userId: Long?,
    @ColumnInfo(name = "create_date")
    var createDate: String?,
    @ColumnInfo(name = "bank_id")
    var bankId: Long?,
    @ColumnInfo(name = "description")
    var description: String?,
    @ColumnInfo(name = "increase")
    var increase: String?,
    @ColumnInfo(name = "decrease")
    var decrease: String?,
    @ColumnInfo(name = "loan_number")
    var loanNumber: String?,
    @ColumnInfo(name = "total")
    var total: Long?,
    @ColumnInfo(name = "type")
    var type: String?
)

用户 DAO:

 @Insert
suspend fun insert(ui: UserInfo): Long

@Update
suspend fun update(ui: UserInfo)

@Insert
suspend fun insertList(ui: MutableList<UserInfo>)

@Delete
suspend fun deleteUser(ui: UserInfo)

@Query("DELETE FROM user_info")
fun deleteAllUser()

@Query("SELECT user_info.user_id, user_info.full_name, transactions.total From user_info JOIN transactions ")
fun joinTable(): LiveData<List<UserAndMoney>>?

@Query("SELECT * from user_info WHERE user_id = :key")
fun get(key: Long): LiveData<UserInfo>?

@Query("SELECT * FROM user_info ORDER BY full_name DESC")
fun getAllUserInfo(): LiveData<List<UserInfo>>

@Query("SELECT * FROM user_info where full_name like '%' || :fullName || '%' ORDER BY full_name ASC")
fun searchUserName(fullName: String): LiveData<List<UserInfo>>

如果你到现在还不清楚,让我为你解惑:

我需要级联删除来删除有关用户和记录的所有内容。

【问题讨论】:

参考room-relationships 【参考方案1】:

CASCADE 是外键约束的一个选项。所以你需要定义外键约束。您可以通过 @Entity 注释在 Room 中定义外键约束。

作为一个例子,看起来事务通过var userId: Long?,(列名 user_id)与 UserInfo 相关,您可以:-

@Entity(tableName = "transactions",
    foreignKeys = [
        ForeignKey(
            entity = UserInfo::class,
            parentColumns = ["user_id"],
            childColumns = ["user_id"],
            onDelete = ForeignKey.CASCADE, //<<<<<
            onUpdate = ForeignKey.CASCADE // Optional
        )
    ]
)
data class Transactions(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "trans_id")
    var transId: Long = 0L,
    @ColumnInfo(name = "user_id", index = true) // <<<<< best to have an index on the column, not required
    var userId: Long?,
    @ColumnInfo(name = "create_date")
    var createDate: String?,
    @ColumnInfo(name = "bank_id")
    var bankId: Long?,
    @ColumnInfo(name = "description")
    var description: String?,
    @ColumnInfo(name = "increase")
    var increase: String?,
    @ColumnInfo(name = "decrease")
    var decrease: String?,
    @ColumnInfo(name = "loan_number")
    var loanNumber: String?,
    @ColumnInfo(name = "total")
    var total: Long?,
    @ColumnInfo(name = "type")
    var type: String?
)

注意

约束强制执行引用完整性,即如果 user_id 值不是 user_info 表的 user_id 列中存在的值,则无法插入/更新事务。

CASCADE onUpdate 会将 user_info 表中 user_id 值的更改级联到相应的事务。

附加

有人告诉我必须使用 Cascade delete,但我没有找到太多相关信息。

您被告知的内容不正确。您可以在没有 ON DELETE CASCADE 或没有外键约束的情况下复制该功能。

你可以使用

@Query("DELETE FROM transaction WHERE user_id=:userId")
fun cascadeDeletionsFromUser(userId: Long)
注意,如果事务表中存在外键约束但未指定 onDelete 操作,则必须在删除 user_info 行之前运行 cascadeDeletionsFromUser 函数。否则无法删除 user_info 行,因为 FK 约束会禁止删除。

如果您有一个抽象类而不是接口,那么您可以:-

@Query("DELETE FROM user_info WHERE user_id=:userId")
abstract fun deleteUserById(userId: Long)

@Query("DELETE FROM transactions WHERE user_id=:userId")
abstract fun cascadeDeletionsFromUser(userId: Long)

@Transaction
@Query("")
fun deleteUserWithCascade(userId: Long) 
    cascadeDeletionsFromUser(userId)
    deleteUserById(userId)

并使用deleteUserWithCascade函数一次性删除交易和用户。

使用ON DELETE CASCADE 更方便,尤其是如果您有多个深度关系(当确定孩子变得更复杂时)

【讨论】:

谢谢你拯救了我的一天。谢谢:)

以上是关于android房间数据库KOTLIN中的级联删除的主要内容,如果未能解决你的问题,请参考以下文章

JPA Hibernate - 数据库和注释中的级联删除

关于mysql的级联删除(之前好多人咨询过我)

关于数据的级联删除和更新

Hibernate的一对多自关联中的级联删除问题

SQL中的级联菱形删除

mysql数据库的级联复制