android - 如果存在则更新记录,否则在 Room 中插入新记录

标签 android rx-java2 android-room android-mvvm

我是 Room、Rxjava 和其他 android 架构组件的新手。我正在尝试更新/插入 2 条记录(如果行已经存在,请更新它。否则插入一个新行。)我尝试按照以下方式进行操作。但是,我没有工作。

游戏 Activity :

public class GameActivity extends AppCompatActivity {

...

    public void onGameWinnerChanged(Player winner) {


    mDisposable.add(gameViewModel.updateDb(winner)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
            .subscribe(() -> Log.e("Success!!!", "updated records")
                    , throwable -> {
                throwable.printStackTrace();
            }));        
      }
}

游戏 View 模型:

public class GameViewModel extends ViewModel {

    ...

    public Completable updateDb(Player winner) {

        return Completable.fromAction(() -> {
            updateWinner(winner);
            Player loser = game.player1 == winner ? game.player2 : game.player1;
            updateLoser(loser);
        });
    }

    private void updateLoser(Player loser) {

           User user = userDataSource.getSingleRecordFromName(loser.name);
        if (user != null) {
            user.loss++;
            userDataSource.updateRecord(user);
        } else {
            user = new User(loser.name, "", 0, 0, 1);
            userDataSource.insertOrUpdateUser(user);
        }
    }

    private void updateWinner(Player winner) {

      User user = userDataSource.getSingleRecordFromName(winner.name);
      if (user != null) {
            user.wins++;
            userDataSource.updateRecord(user);
      } else {
            user = new User(winner.name, "", 0, 1, 0);
            userDataSource.insertOrUpdateUser(user);
      }
   }
}

本地用户数据源

public class LocalUserDataSource implements UserDataSource {

    private DaoAccess daoAccess;

    public LocalUserDataSource(DaoAccess daoAccess){
        this.daoAccess=daoAccess;
    }

    @Override
    public Flowable<List<User>> getUsers() {
        return daoAccess.fetchAllData();
    }

    @Override
    public void insertOrUpdateUser(User user) {
        Log.e("local user ds","insertOrUpdateUser");
        daoAccess.insertOnlySingleRecord(user);
    }

    @Override
    public User getSingleRecordFromName(String strName) {
        return daoAccess.getSingleRecord(strName);
    }


    @Override
    public void updateRecord(User user) {
        daoAccess.updateRecord(user);
    }

    @Override
    public void deleteRecord(User user) {
        daoAccess.deleteRecord(user);
    }
}

道访问

@Dao
public interface DaoAccess  {

    @Insert
    void insertOnlySingleRecord(User user);

    @Query("SELECT * FROM User")
    Flowable<List<User>> fetchAllData();

    @Query("SELECT * FROM User WHERE name =:strName")
    User getSingleRecord(String strName);

    @Update
    void updateRecord(User user);

    @Delete
    void deleteRecord(User user);
}

问题是,当我尝试运行时,如果我尝试在 GameViewModel 类的以下行中插入任何不在数据库中的用户,则会发生 NullPointer 异常。

User user = userDataSource.getSingleRecordFromName(loser.name);

谁能告诉我哪里错了或者我该怎么做?

编辑

我想做的是首先获取一个用户(如果它在数据库中),更新增量或减量分数(如果赢家则 +1 赢家列,如果输家则 +1 输家列)。 如果表中不存在该用户,则创建一个新条目。

最佳答案

您的用户 Dao 应该如下所示

@Dao
public interface DaoAccess  {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertOnlySingleRecord(User user);

    @Query("SELECT * FROM User")
    Flowable<List<User>> fetchAllData();

    @Query("SELECT * FROM User WHERE lower(name) = lower(:strName) limit 1")
    User getSingleRecord(String strName);

    @Update
    void updateRecord(User user);

    @Delete
    void deleteRecord(User user);
}

你的用户实体应该是这样的

 @Entity(tableName = "user_table", indices = @Index(value = {"name"}, unique = true))
public class UserEntity {

    @PrimaryKey(autoGenerate = true)
    private int id;

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

关于android - 如果存在则更新记录,否则在 Room 中插入新记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49829853/

相关文章:

android - RxJava2 表单验证

java - 等待方法响应而不阻塞其他HTTP请求的流程

android - Spek + Retrofit api 测试崩溃

android - 将 S3 Bucket 与 Dynamodb android 链接起来?

android - 是否有一种标准的方法来提示应该一次读取一个数字?

android - 如何在 Android 上省略 Activity 标题

java - Android : How to OnConflictStrategy. 替换但保留一个特定字段

sqlite - 房间的日历类型转换器(Kotlin)

android - 如何在android房间实体中注释默认值?

java - SQLite 'No such table error'