web-dev-qa-db-fra.com

mise à jour de la pièce (ou insertion s'il n'y en a pas) et nombre de retours de lignes modifiées

J'ai besoin d'une mise à jour et si ce n'est pas le cas, insérez une ligne dans la base de données ROOM.

Je fais ceci: productRepository.updateProducts(productsResponse.getProductItems());

Et:

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

Et chez DAO:

@Insert
void insert(Product products);

Mais j'ai méthode 

@Update
void update(Product product);

Et j'ai quelques questions:

  1. les deux méthodes sont nulles. Comment puis-je retourner un indicateur de produit ou booléen enregistré ou un nombre inséré après l'insertion?

  2. si j'essaie d'appeler update et que je n'ai pas rangé, sera-t-il inséré?

  3. Comment puis-je mettre à jour (sinon insérer) une ligne et renvoyer le nombre de mises à jour ou les lignes insérées?

6
ip696
  1. Une méthode, annotée avec @Insert peut renvoyer une long. C'est l'ID nouvellement généré pour la ligne insérée. Une méthode annotée avec @Update peut renvoyer une int. C'est le nombre de lignes mises à jour.

  2. update tentera de mettre à jour tous vos champs en utilisant la valeur de la clé primaire dans une clause where. Si votre entité n'est pas encore conservée dans la base de données, la requête update ne pourra pas trouver une ligne et ne mettra rien à jour. 

  3. Vous pouvez utiliser @Insert(onConflict = OnConflictStrategy.REPLACE). Cela tentera d'insérer l'entité et, s'il existe une ligne existante ayant la même valeur d'ID, elle sera supprimée et remplacée par l'entité que vous essayez d'insérer. Sachez que si vous utilisez des identifiants générés automatiquement, cela signifie que la ligne résultante aura un identifiant différent de l'original qui a été remplacé. Si vous souhaitez conserver l'ID, vous devez proposer un moyen personnalisé de le faire.

19
Danail Alexiev

Vous pouvez vérifier votre base de données s'il existe déjà un élément avec un champ spécifique, par exemple:

@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 est votre objet et dans votre 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

Vous pouvez vérifier ci-dessous la méthode insertModel () où obtenir les méthodes onComplete () et onError ():

    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

Cela fait longtemps, mais cette question n'a pas de réponse acceptée, je vais donc donner mon point de vue.

Comme @Danail Alexiev, @Insert peut renvoyer une long. @Update peut retourner une int

Mais dans quel but utilisez-vous update? Si vous souhaitez simplement que l'objet entier soit remplacé par le nouvel objet, spécifiez simplement la variable OnConflictStrategy

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

Le résultat sera: les éléments qui n'existent pas seront ajoutés, les éléments qui existent déjà seront remplacés par les nouveaux. 

Dans le cas où vous devez mettre à jour un seul paramètre (comme la quantité par exemple), vous pouvez faire quelque chose comme ceci. 

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

Le résultat sera: Essayez de rechercher l'élément dans la base de données. Le cas échéant, mettez à jour une propriété, sinon insérez simplement un nouvel élément. Il vous suffit donc d'appeler une méthode insertOrUpdate à partir de votre DAO. 

0
Rainmaker