Room autoGenerate主键初始值设0及应用启动自动插入数据问题咨询
问题1解决方案
当你用@PrimaryKey(autoGenerate = true)修饰基本类型int的主键时,Room会默认将传入的0值判定为「未主动设置主键」,触发自动生成逻辑,SQLite自增主键默认起始值为1,所以手动调用setId(0)也会被覆盖。
推荐修改方案
将主键类型从基本类型int改为包装类型Integer,修改后实体类代码如下:
@Entity(tableName = "group_table") public class Group { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") private Integer id; public void setId(Integer id) { this.id = id; } // 其余Getter、Setter保持原有逻辑不变 }
修改后规则为:
- 主动调用
setId(0)传入有效值时,Room会直接使用你设置的0作为主键插入 - 传入
id = null时,才会触发自动生成主键的逻辑
如果你的场景不需要后续主键自增,也可以直接去掉autoGenerate = true属性,所有主键手动维护即可。
问题2解决方案
步骤1:新增Dao层方法
在Group对应的Dao接口中添加查询指定id记录和插入的方法:
@Dao public interface GroupDao { // 查询id为0的记录,返回null代表不存在该记录 @Query("SELECT * FROM group_table WHERE id = 0 LIMIT 1") Group getDefaultGroup(); @Insert void insertGroup(Group group); }
步骤2:添加检测插入逻辑
推荐将逻辑放在Room数据库的初始化回调中,保证数据库创建/打开时自动执行,示例代码如下:
public abstract class AppDatabase extends RoomDatabase { public abstract GroupDao groupDao(); private static volatile AppDatabase INSTANCE; public static AppDatabase getInstance(Context context) { if (INSTANCE == null) { synchronized (AppDatabase.class) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "你的数据库名.db") .addCallback(new Callback() { @Override public void onCreate(@NonNull SupportSQLiteDatabase db) { super.onCreate(db); // 数据库首次创建时异步执行检测 new Thread(() -> { GroupDao dao = INSTANCE.groupDao(); if (dao.getDefaultGroup() == null) { Group defaultGroup = new Group(); defaultGroup.setId(0); // 补充默认记录的其余字段赋值 dao.insertGroup(defaultGroup); } }).start(); } @Override public void onOpen(@NonNull SupportSQLiteDatabase db) { super.onOpen(db); // 如果需要每次应用启动打开数据库都检测,就把上面的逻辑挪到这里 } }) .build(); } } } return INSTANCE; } }
注意:Room的数据库操作不允许在主线程执行,所以需要放在子线程、协程或者RxJava等异步环境中运行。
内容的提问来源于stack exchange,提问作者andtompoi
相关产品推荐
相关产品推荐

