关于android:room更新(或如果不存在,则插入)行并返回更改计数的行

room update (or insert if not exist) rows and return count changed rows

我需要更新,如果不存在,请向ROOM DB插入行。

我这样做:productRepository.updateProducts(productsResponse.getProductItems());

和:

1
2
3
4
5
6
7
8
9
@Override
public void updateProducts(final List<ProductItem> products) {
    new Thread(() -> {
        for (ProductItem item : products) {
            Product product = createProduct(item);
            productDao.insert(product);
        }
    }).start();
}

在DAO中:

1
2
@Insert
void insert(Product products);

但是我有方法

1
2
@Update
void update(Product product);

我有一些问题:

  • 两种方法均无效。 插入后如何返回已保存的Product或boolean标志或插入的计数?

  • 如果我尝试调用update并且没有行,是否将其插入?

  • 如何更新(如果不是-插入)行并返回计数更新或插入的行?


  • @Insert注释的方法可以返回long。这是插入行的新生成的ID。用@Update注释的方法可以返回int。这是更新的行数。

  • update将尝试使用where子句中的主键值更新所有字段。如果您的实体尚未持久存储在数据库中,则update查询将无法找到行,也不会更新任何内容。

  • 您可以使用@Insert(onConflict = OnConflictStrategy.REPLACE)。这将尝试插入实体,并且如果存在具有相同ID值的现有行,它将删除该实体并将其替换为您尝试插入的实体。请注意,如果您使用的是自动生成的ID,这意味着结果行将具有与替换的原始ID不同的ID。如果要保留ID,则必须想出一种自定义的方法。


  • 已经有一段时间了,但是这个问题没有一个可以接受的答案,所以我会考虑一下。

    正如@Danail Alexiev所说的@Insert可以返回long@Update可以返回int

    但是,您出于什么目的使用更新?如果只想用新对象替换整个对象,则只需指定OnConflictStrategy

    1
    2
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insert(Product products);

    结果将是:将添加不存在的项目,将已存在的项目替换为新项目。

    如果您只需要更新一个参数(例如数量),则可以执行以下操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
      @Insert(onConflict = OnConflictStrategy.REPLACE)
      void insert(Product products);

      @Query("SELECT * from item WHERE id= :id")
      void getItemById(int id): List<Product>

      @Query("UPDATE item SET quantity = quantity + 1 WHERE id = :id")
      void updateQuantity(int id)

      void insertOrUpdate(Product item) {
                    Product itemFromDB = getItemById(item.getId())
                    if (itemFromDB == null)
                        insert(item)
                    else
                        updateQuantity(item.getId())
                }
            }

    结果将是:尝试在数据库中查找项目,如果发现更新属性,则不只是插入一个新项目。因此,您只需要从DAO调用一种方法insertOrUpdate


    您可以检查数据库是否已存在具有特定字段的项目,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    @Query("SELECT id FROM items WHERE id = :id LIMIT 1")
    fun getItemId(id: String): String?

    @Insert
    fun insert(item: Item): Long

    @Update(onConflict = OnConflictStrategy.REPLACE)
    fun update(item: Item): Int

    Item是您的对象,并且在您的代码中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     fun insertOrUpdate(item: Item) {
                database.runInTransaction {
                    val id = getItemDao().getItemId(item.id)

                    if(id == null)
                        getItemDao().insert(item)
                    else
                        getItemDao().update(item)
                }
            }


    您可以在下面的方法insertModel()中进行检查,可以在其中获取onComplete()和onError()方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
        val db: AppDatabase = Room.databaseBuilder(mCtx, AppDatabase::class.java,"db_nam.sqlite").build()

        companion object {
            @SuppressLint("StaticFieldLeak")
            private var mInstance: DatabaseClient? = null

            @Synchronized
            fun getInstance(mCtx: Context): DatabaseClient {
                if (mInstance == null) {
                    mInstance = DatabaseClient(mCtx)
                }
                return mInstance as DatabaseClient
            }
        }

        // SEE HERE FOR INSERTING DATA SUCCESSFULLY AND ERROR CODE  
        private fun insertModel(rss_Model: RSS_Model) {
            Completable.fromAction {

                db.database_dao().insertRSS(rss_Model)

            }.observeOn(AndroidSchedulers.mainThread())
                    .subscribeOn(Schedulers.io()).subscribe(object : CompletableObserver {
                        override fun onSubscribe(d: Disposable) {}

                        override fun onComplete() {
                            // Log.e("onComplete","GET SUCCESS HERE")
                        }

                        override fun onError(e: Throwable) {
                            // Log.e("onError","onError")
                        }
                    })
        }

    您应该使用Rx Android Single来解决此问题。例:

    1
    2
    @Query("SELECT * FROM subjectFormTable WHERE study_subject_id ==:subjectFormId")
    fun getSubjectForm(subjectFormId: Int): Single<SubjectFormEntity>

    我们用

    1
    val compositeDisposable = CompositeDisposable()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    compositeDisposable.add(
                subjectFormDao.getSubjectForm(studySubjectId)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    Log.e(TAG,"successful")
                }, {
                    Log.e(TAG,"error"+it.message)
                    //Insert or Update data here
                })
        )