android 房间数据库 KOTLIN 中的级联删除
cascade delete in android room database KOTLIN
Whosebug 中有很多这样的问题,但其中大部分与房间数据库无关,所以我不得不问一个新问题。
我有一个使用房间数据库的应用程序,它有近 4 个表并且这些表之间有很大的关系,所以例如当我删除用户列表片段中的用户时,该用户删除(仅用户名和一些个人信息) 但用户的 TRANSACTIONS 和 LOANS 没有被删除。
有人告诉我必须使用 Cascade delete 但我没有找到太多相关信息。
我的用户class 型号:
@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?,
)
交易模式class:
@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>>
如果到现在为止您还不清楚,让我为您简化一下:
我需要级联删除删除关于用户和记录的所有内容。
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 列中存在的值,则事务不能 inserted/updated =] table.
CASCADE onUpdate 会将 user_info table 中的 user_id 值的更改级联到相应的事务。
额外
Someone told me I have to use Cascade delete but I didn't find much info about it.
你被告知的是不正确的。您可以在没有 ON DELETE CASCADE
或没有外键约束的情况下复制功能。
你可以使用
@Query("DELETE FROM transaction WHERE user_id=:userId")
fun cascadeDeletionsFromUser(userId: Long)
- 注意到如果外键约束存在于事务 table 但没有指定 onDelete 操作,那么
cascadeDeletionsFromUser
函数必须在 运行 之前user_info 行已删除。否则无法删除 user_info 行,因为 FK 约束会禁止删除。
如果你有一个抽象class而不是接口那么你可以有:-
@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
更方便,特别是如果你有多个深度的关系(当它变得有点复杂时确定 children)
Whosebug 中有很多这样的问题,但其中大部分与房间数据库无关,所以我不得不问一个新问题。
我有一个使用房间数据库的应用程序,它有近 4 个表并且这些表之间有很大的关系,所以例如当我删除用户列表片段中的用户时,该用户删除(仅用户名和一些个人信息) 但用户的 TRANSACTIONS 和 LOANS 没有被删除。 有人告诉我必须使用 Cascade delete 但我没有找到太多相关信息。
我的用户class 型号:
@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?,
)
交易模式class:
@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>>
如果到现在为止您还不清楚,让我为您简化一下:
我需要级联删除删除关于用户和记录的所有内容。
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 列中存在的值,则事务不能 inserted/updated =] table.
CASCADE onUpdate 会将 user_info table 中的 user_id 值的更改级联到相应的事务。
额外
Someone told me I have to use Cascade delete but I didn't find much info about it.
你被告知的是不正确的。您可以在没有 ON DELETE CASCADE
或没有外键约束的情况下复制功能。
你可以使用
@Query("DELETE FROM transaction WHERE user_id=:userId")
fun cascadeDeletionsFromUser(userId: Long)
- 注意到如果外键约束存在于事务 table 但没有指定 onDelete 操作,那么
cascadeDeletionsFromUser
函数必须在 运行 之前user_info 行已删除。否则无法删除 user_info 行,因为 FK 约束会禁止删除。
如果你有一个抽象class而不是接口那么你可以有:-
@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
更方便,特别是如果你有多个深度的关系(当它变得有点复杂时确定 children)