You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Room数据库仅能插入单条数据,新增/修改操作失效求助

Android Room数据库插入/修改异常排查与解决

现象描述

  • 在PersonRoomDatabase的回调中插入person1和person2,Database Inspector仅显示person1
  • MainActivity中插入person3未成功
  • 修改person1名称后,数据库中仍显示原名称"saul"
  • 仅person1能正常存在,无法新增或修改其他Person对象

相关代码

1. PersonRoomDatabase类

@Database(entities = {Person.class},version = 1,exportSchema = false)
public abstract class PersonRoomDatabase extends RoomDatabase {

   public abstract PersonDAO personRoomDAO();

private static volatile PersonRoomDatabase INSTANCE;
public static final int NUMBER_OF_THREADS=4;
static final ExecutorService databaseWriteExecutor=
        Executors.newFixedThreadPool(NUMBER_OF_THREADS);

// 单例模式确保仅存在一个数据库实例
static final PersonRoomDatabase getDatabase(final Context context){
    if (INSTANCE==null){
        synchronized (PersonRoomDatabase.class){
            if (INSTANCE==null){
                INSTANCE= Room.databaseBuilder(context.getApplicationContext(),
                                PersonRoomDatabase.class,"person_database")
                        .addCallback(sRoomDatabaseCallback)
                        .build();
            }
        }
    }
    return INSTANCE;
}

private static RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() {
    @Override
    public void onCreate(@NonNull SupportSQLiteDatabase db) {
        super.onCreate(db);

        databaseWriteExecutor.execute(() -> {
          
            PersonDAO dao = INSTANCE.personRoomDAO();
            dao.deleteAll();

            Person person1=new Person("saul","goodman");
            dao.insert(person1);

            Person person2=new Person("walter","white");
            dao.insert(person2);


        });
    }
};
}

2. PersonDAO接口

@Dao
public interface PersonDAO {

@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(Person person);

@Query("DELETE FROM person_table")
void deleteAll();

@Query("SELECT * FROM person_table ORDER BY name ASC")
LiveData<List<Person>> selectAllPerson();

}

3. PersonViewModel类

public class PersonViewModel extends AndroidViewModel {

private PersonRepository personViewModelRepository;

private final LiveData<List<Person>> allPersonViewModel;

public PersonViewModel(@NonNull Application application) {
    super(application);
    personViewModelRepository=new PersonRepository(application);
    allPersonViewModel=personViewModelRepository.getAllPersonsRepository();
}

public LiveData<List<Person>> getAllPersonViewModel(){return allPersonViewModel;}

public void insert(Person person){ personViewModelRepository.insert(person);}

public void deleteAll(){personViewModelRepository.deleteAll();}
}

4. PersonRepository类

public class PersonRepository {
private PersonDAO personRepositoryDAO;
private LiveData<List<Person>> allPersons;

PersonRepository (Application application){
    PersonRoomDatabase db=PersonRoomDatabase.getDatabase(application);

    personRepositoryDAO=db.personRoomDAO();

    allPersons=personRepositoryDAO.selectAllPerson();
}

LiveData<List<Person>> getAllPersonsRepository() {
    return allPersons;
}

void insert(Person person){
    PersonRoomDatabase.databaseWriteExecutor.execute(() ->
            personRepositoryDAO.insert(person));
}
void deleteAll(){
    PersonRoomDatabase.databaseWriteExecutor.execute(() ->
            personRepositoryDAO.deleteAll());
}

}

5. Person实体类

@Entity(tableName = "person_table")
public class Person {

@PrimaryKey
@ColumnInfo(name = "id")
private int id;

@ColumnInfo(name = "name")
private String name;

@ColumnInfo(name = "lastName")
private String lastName;

public Person(){

}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

public void setName(String name) {
    this.name = name;
}

public Person(String name, String lastName) {
    this.name = name;
    this.lastName = lastName;
}

public void setId(int id) {
    this.id = id;
}

public int getId() {
    return id;
}

public String getName() {
    return name;
}

public String getLastName() {
    return lastName;
}

}

6. MainActivity类

public class MainActivity extends AppCompatActivity {
public Person person;
private PersonViewModel personViewModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    personViewModel= new ViewModelProvider.AndroidViewModelFactory(MainActivity.this
            .getApplication())
            .create(PersonViewModel.class);

    Person person3=new Person("jesse","pinkman");
    personViewModel.insert(person3);

    personViewModel.getAllPersonViewModel().observe(this,person ->
            Log.d("Observe", "onCreate: "+person.get(0).getName())
    );
}
}

问题根源

核心问题出在Person实体类的主键设置:

  1. 将id设为@PrimaryKey,但创建Person对象时未给id赋值,默认int类型的id值为0
  2. 插入person1时,id=0被写入数据库;插入person2、person3时,id同样是0,DAO的@Insert(onConflict = OnConflictStrategy.IGNORE)注解会在主键冲突时忽略插入操作,导致person2、person3无法写入
  3. 修改person1名称时,若重新插入id=0的对象,同样触发IGNORE策略,数据库记录不会更新

解决方案

1. 让主键自动生成(推荐)

修改Person实体类的主键注解,添加autoGenerate = true,让Room自动为每条记录生成唯一id:

@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private int id;

此后每次插入新Person对象时,Room会自动分配递增的唯一id,避免主键冲突,person2、person3可正常插入。

2. 添加更新方法支持数据修改

在DAO接口中新增更新方法,用于修改已有记录:

@Dao
public interface PersonDAO {
    // ... 原有方法
    @Update
    void update(Person person);
}

修改person1时,先查询到该对象,修改属性后调用update()方法,而非重新插入。

3. 验证步骤

  1. 修改实体类后,卸载App或清除App数据(让Room重新创建数据库)
  2. 运行App,查看Database Inspector确认person1、person2均显示
  3. 测试插入person3,确认正常添加
  4. 测试修改person1名称,调用update方法后确认数据库记录更新

内容的提问来源于stack exchange,提问作者mehmet ali duran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 04:48:28