我想自动递增 Room 中的某个实体表。我正在房间中插入桌子列表。
ShopMenuEntity.kt
@Entity(tableName = ShopMenuEntity.TABLE_NAME)
data class ShopMenuEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = COLUMN_ID)
var id: Int = 0,
var level:Int? = null,
@ColumnInfo(name = COLUMN_PARENT_ID)
var parentId: Int = -1
) {
companion object {
const val TABLE_NAME = "shop_menu_table"
const val COLUMN_ID = "menu_id"
const val COLUMN_PARENT_ID = "parentId"
fun mapHttpResponse(subMenu: NewShopMenuResponse,parentId: Int): ShopMenuEntity {
return ShopMenuEntity(
// How can I auto increment below statement?
id = subMenu.id ?: -1,
level = subMenu.level,
parentId = parentId,
)
}
}
}
id = subMenu.id?: -1
必须保存在房间
我也尝试过将其设置为0。但没有工作
我的实现的详细代码在另一个问题
autoGenerate = true
包含 AUTOINCREMENT
关键字,这会导致 SQLite(Room 包装的数据库管理器)在没有给定值的情况下生成列的值。 它不会在对象中生成值,这似乎是您的期望。
Room,在插入时认为 0 表示没有值,因此不提供任何值,包括 -1 在内的任何其他整数值将导致尝试插入具有该列值的行。由于该列必须是主键,因此值必须是唯一的,因此如果插入了 -1 值,则不会插入值为 -1 的后续插入。
您似乎正在尝试确定/预测/假设生成的值。没有必要,如果您使用 Room 的
@Insert
那么生成的值将作为 Long 返回,或者在未插入行的情况下,没有错误,则返回值将为 -1。
虽然很有可能,生成的值将比曾经插入的最高值大 1,或者在第一个插入行 1 的情况下。但是,不能保证该值将大 1。
简而言之,您应该插入行,然后获取值(例如,利用从
@Insert
返回的结果),而不是尝试对值做出假设。
示范
使用以下代码:-
@Entity(tableName = ShopMenuEntity.TABLE_NAME)
data class ShopMenuEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = COLUMN_ID)
var id: Int = 0,
var level:Int? = null,
@ColumnInfo(name = COLUMN_PARENT_ID)
var parentId: Int = -1
) {
companion object {
const val TABLE_NAME = "shop_menu_table"
const val COLUMN_ID = "menu_id"
const val COLUMN_PARENT_ID = "parentId"
/*
fun mapHttpResponse(subMenu: NewShopMenuResponse,parentId: Int): ShopMenuEntity {
return ShopMenuEntity(
// How can I auto increment below statement?
id = subMenu.id ?: -1,
level = subMenu.level,
parentId = parentId,
)
}
*/
}
}
addSubShopMenuEntityAndItsParent
界面中的 ShopMenuDAO
):-
@Dao
interface ShopMenuDAO {
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(shopMenuEntity: ShopMenuEntity): Long
@Query("SELECT coalesece(max(${ShopMenuEntity.COLUMN_ID}),-1) FROM ${ShopMenuEntity.TABLE_NAME}")
fun getLastInsertedShopMenuEntityId(): Int
/* An example of how you could achieve what appears to be required */
@Transaction /* Do everything with a single transaction */
@Query("") /* fool Room into think this should be in a transaction */
fun addSubShopMenuEntityAndItsParent(subShopMenuEntity: ShopMenuEntity, parentShopMenuEntity: ShopMenuEntity, parentId: Long?=null): ShopMenuEntity {
var parentIdToUse = parentId
if (parentId==null) {
val insertedParentId = insert(parentShopMenuEntity)
/* If not inserted then return ShopMenuEntity indicating parent not inserted i.e. id = -99 */
if (insertedParentId == -99L) return ShopMenuEntity(-1)
parentIdToUse = insertedParentId
} else {
/* Supplying the Parent ID so use that as parent (SHOULD) already exist */
parentIdToUse = parentId;
}
subShopMenuEntity.parentId = parentIdToUse.toInt()
val insertedSubId = insert(subShopMenuEntity)
/* If not inserted then return ShopMenuEntity indicating that sub was not inserted i.e. -1 */
if (insertedSubId == -1L) {
return ShopMenuEntity(-1)
}
subShopMenuEntity.id = insertedSubId.toInt()
return subShopMenuEntity
}
}
getLastInsertedShopMenuEntityId
,它应该返回最后插入的ID(警告如果插入指定ID的海湾,情况可能并不总是如此)允许实际演示基本的
@Database
带注释的类:-
/* Basic @Database abstract class */
@Database(entities = [ShopMenuEntity::class], exportSchema = false, version = 1)
abstract class ShopDatabase: RoomDatabase() {
abstract fun getShopMenuDAO(): ShopMenuDAO
companion object {
private var instance: ShopDatabase?=null
fun getInstance(context: Context): ShopDatabase {
if (instance==null) {
instance = Room.databaseBuilder(context,ShopDatabase::class.java,"whatever.db")
.allowMainThreadQueries() /* use the main thread for brevity */
.build()
}
return instance as ShopDatabase
}
}
}
最后一些实际演示的活动代码:-
class MainActivity : AppCompatActivity() {
lateinit var db: ShopDatabase
lateinit var dao: ShopMenuDAO
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = ShopDatabase.getInstance(this)
dao = db.getShopMenuDAO()
/* Normal insert of a shop only */
val s1Id = dao.insert(ShopMenuEntity(0,1))
Log.d("DBINFO","The id of the last inserted shop was ${dao.getLastInsertedShopMenuEntityId()}")
/* Insert of a shop with a parent, the parent's id being passed (the parent ShopMenuEntity is ignored) */
val s2 = dao.addSubShopMenuEntityAndItsParent(ShopMenuEntity(0,100),ShopMenuEntity(-100),s1Id)
if (s2.id < 0) Log.d("DBINFO","Oooops something not quite right as id of subShop is less than 0, it was ${s2.id}")
Log.d("DBINFO","The id of the last inserted shop was ${dao.getLastInsertedShopMenuEntityId()}")
/* Add a subShop along with the new parentShop */
val s3 = dao.addSubShopMenuEntityAndItsParent(ShopMenuEntity(level = 3), ShopMenuEntity(99,0),null)
if (s3.id < 0) Log.d("DBINFO","Oooops something not quite right as id of subShop is less than 0, it was ${s3.id}")
Log.d("DBINFO","The id of the last inserted shop was ${dao.getLastInsertedShopMenuEntityId()}")
for (sme in dao.getAllShopMenuEntities()) {
Log.d("DBINFO","Shop ID is ${sme.id} Level is ${sme.level} Parent ID is ${sme.parentId}")
}
}
}
当上面的代码运行时(作为一个新的应用程序,它不是设计来重新运行的),那么日志包含:-
2023-08-04 10:46:44.820 D/DBINFO: The id of the last inserted shop was 1
2023-08-04 10:46:44.825 D/DBINFO: The id of the last inserted shop was 2
2023-08-04 10:46:44.845 D/DBINFO: The id of the last inserted shop was 100
2023-08-04 10:46:44.847 D/DBINFO: Shop ID is 1 Level is 1 Parent ID is -1
2023-08-04 10:46:44.847 D/DBINFO: Shop ID is 2 Level is 100 Parent ID is 1
2023-08-04 10:46:44.847 D/DBINFO: Shop ID is 99 Level is 0 Parent ID is -1
2023-08-04 10:46:44.847 D/DBINFO: Shop ID is 100 Level is 3 Parent ID is 99
可以看出:-
ID 1、2 和 100 已生成,并且 ID 99 已指定并相应设置(不建议指定 id,而是生成它们)。
父母已相应设置,即
@Insert
获取的父级 ID)addSubShopMenuEntityAndItsParent
函数指定为新插入(这可能相当于您的 mapHttpResponse
函数)。如果使用App Inspection,则以上 4 行将按以下方式反映:-
此外,通过“打开新查询选项卡”使用查询
SELECT * FROM sqlite_sequence;
,然后您会得到:-
即100的最高分配ID已存储在sqlite_sequence表中(因为已使用AUTOINCRMENT)。因此,当生成 menu_id 列的值时,它将是 1 + 最高的 menu_id 值和表中保存在 sqlite_sequence 中的值(sqlite_sequence 表的名称列)中的较高者。
您可能希望参考 https://www.sqlite.org/autoinc.html 了解有关自动增量的更多信息。