Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Batch InsertOrUpate in Room ORM

I am trying hands with android room ORM. Many ORM's have this method insertOrUpdate method. How do I achieve this? I want to insert or update multiple rows in a single transaction,i.e., if row is present then update it else insert a new entry.

like image 559
androider Avatar asked Jan 06 '18 07:01

androider


People also ask

Is room DB an ORM?

Is Android Room an ORM? Room isn't an ORM; instead, it is a whole library that allows us to create and manipulate SQLite databases more easily. By using annotations, we can define our databases, tables, and operations.

What is room ORM?

Room is an ORM, Object Relational Mapping library. In other words, Room will map our database objects to Java objects. Room provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.

What is DAO in Room?

When you use the Room persistence library to store your app's data, you interact with the stored data by defining data access objects, or DAOs. Each DAO includes methods that offer abstract access to your app's database. At compile time, Room automatically generates implementations of the DAOs that you define.


2 Answers

You can do an insert with a conflict resolution set to replace:

@Dao
public interface MyDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public void insertUsers(User... users);
}

Notice that (from Room documentation):

Note: SQLite handles @Insert(onConflict = REPLACE) as a set of REMOVE and REPLACE operations instead of a single UPDATE operation. This method of replacing conflicting values could affect your foreign key constraints. For more details, see the SQLite documentation for the ON_CONFLICT clause.

In Room, this single insert statement is run inside a transaction, so it should be safe most of the time.

Alternatively, you can run your statements inside a transaction:

myDb.runInTransaction(new Runnable() {
     @Override
     public void run() {
         // Your operations
     }
});

Or, from this other StackOverflow answer:

@Dao
public abstract class ProductDao {
    @Insert
    public abstract void insert(Product product);

    @Delete
    public abstract void delete(Product product);

    @Transaction
    public void insertAndDeleteInTransaction(Product newProduct, Product oldProduct) {
        // Anything inside this method runs in a single transaction.
        insert(newProduct);
        delete(oldProduct);
    }
}
like image 102
Xavier Rubio Jansana Avatar answered Dec 06 '22 19:12

Xavier Rubio Jansana


For batch transaction insert/update you can do that Transaction Annotation:

Annotating a method with @Transaction makes sure that all database operations you’re executing in that method will be run inside one transaction. The transaction will fail when an exception is thrown in the method body.

@Dao
abstract class UserDao {

    @Transaction
    open fun updateData(users: List<User>) {
        deleteAllUsers()
        insertAll(users)
    }
    @Insert
    abstract fun insertAll(users: List<User>)
    @Query("DELETE FROM Users")
    abstract fun deleteAllUsers()
}

You might want to use the @Transaction annotation for @Query methods that have a select statement, in the following cases:

When the result of the query is fairly big. By querying the database in one transaction, you ensure that if the query result doesn’t fit in a single cursor window, it doesn’t get corrupted due to changes in the database between cursor window swaps. When the result of the query is a POJO with @Relation fields. The fields are queries separately so running them in a single transaction will guarantee consistent results between queries. @Delete, @Update and @Insert methods that have multiple parameters are automatically run inside a transaction.

like image 25
Sofien Rahmouni Avatar answered Dec 06 '22 17:12

Sofien Rahmouni