web-dev-qa-db-de.com

raumaktualisierung (oder Einfügen, falls nicht vorhanden) Zeilen und Anzahl geänderter Zeilen zurückgeben

Ich brauche ein Update und, falls nicht vorhanden, eine Zeile in ROOM DB einfügen.

Ich mache das: productRepository.updateProducts(productsResponse.getProductItems());

Und:

@Override
public void updateProducts(final List<ProductItem> products) {
    new Thread(() -> {
        for (ProductItem item : products) {
            Product product = createProduct(item);
            productDao.insert(product);
        }
    }).start();
}

Und in DAO:

@Insert
void insert(Product products);

Aber ich habe Methode 

@Update
void update(Product product);

Und ich habe einige Fragen:

  1. beide Methoden sind nichtig. Wie kann ich nach dem Einfügen gespeicherte Produkte oder boolesche Flaggen oder eingefügte Zähler zurückgeben?

  2. wenn ich versuche, update aufzurufen, und ich habe keine Zeile, wird es eingefügt?

  3. Wie kann ich die Zeile aktualisieren (falls nicht - einfügen) und die Anzahl der aktualisierten oder eingefügten Zeilen zurückgeben?

6
ip696
  1. Eine mit @Insert kommentierte Methode kann eine long zurückgeben. Dies ist die neu generierte ID für die eingefügte Zeile. Eine mit @Update kommentierte Methode kann eine int zurückgeben. Dies ist die Anzahl der aktualisierten Zeilen.

  2. update versucht, alle Felder mit dem Wert des Primärschlüssels in einer where-Klausel zu aktualisieren. Wenn Ihre Entität noch nicht in der Datenbank gespeichert ist, kann die update-Abfrage keine Zeile finden und aktualisiert nichts. 

  3. Sie können @Insert(onConflict = OnConflictStrategy.REPLACE) verwenden. Dadurch wird versucht, die Entität einzufügen. Wenn eine vorhandene Zeile mit demselben ID-Wert vorhanden ist, wird sie gelöscht und durch die Entität ersetzt, die Sie einfügen möchten. Wenn Sie automatisch generierte IDs verwenden, bedeutet dies, dass die resultierende Zeile eine andere ID hat als das Original, das ersetzt wurde. Wenn Sie die ID beibehalten möchten, müssen Sie einen benutzerdefinierten Weg finden, um dies zu tun.

19
Danail Alexiev

Sie können Ihre Datenbank überprüfen, wenn es bereits ein Element mit einem bestimmten Feld gibt, zum Beispiel:

@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

Artikel ist Ihr Objekt und in Ihrem Code:

 fun insertOrUpdate(item: Item) {
            database.runInTransaction {
                val id = getItemDao().getItemId(item.id)

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

Sie können unten die Methode insertModel () überprüfen, wo Sie die Methoden onComplete () und onError () erhalten können:

    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")
                    }
                })
    }
0
Keyu Zala

Es ist eine Weile her, aber diese Frage hat keine akzeptierte Antwort, also werde ich meine Meinung dazu geben.

Wie @Danail Alexiev kann @Insert eine long zurückgeben. @Update kann eine int zurückgeben. 

Aber für welchen Zweck verwenden Sie Update? Wenn Sie möchten, dass das gesamte Objekt durch das neue Objekt ersetzt wird, geben Sie einfach die Variable OnConflictStrategy an. 

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

Das Ergebnis ist: Nicht vorhandene Elemente werden hinzugefügt, bereits vorhandene Elemente werden durch die neuen ersetzt. 

In dem Fall, dass Sie nur einen Parameter aktualisieren möchten (wie zum Beispiel die Menge), können Sie so etwas tun 

  @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())
            }
        }

Das Ergebnis lautet: Versuchen Sie, das Element in der Datenbank nachzuschlagen, aktualisieren Sie eine Eigenschaft, wenn Sie nicht gerade ein neues Element einfügen. Sie müssen also nur eine Methode insertOrUpdate von Ihrem DAO aufrufen. 

0
Rainmaker