sim
sim

Reputation: 786

Android Room DAO how to run several DAO methods in a single transaction?

Consider the following Room DAO

@Dao
public abstract class JobDao {

    @Insert
    public abstract long insert( Job v );

    @Update 
    public abstract int update( Job v );

    @Insert 
    public abstract long insertPerson( Person p );

    @Update
    public abstract int updatePerson( Person p );

    @Transaction
    public void insertNetJobs( List<NetJob> list ) {
         Timber.d("--- insert page start");
         for( NetJob j : list ) {
             if ( updatePerson( j.getPerson() ) == 0 ) {
                insertPerson( j.getPerson() );
             }

             insert( j.getJob() );
         } 
         Timber.d("--- insert page end");
    }  
}

According to documentation anything inside method marked with @Transaction runs in a single transaction. But in reality it runs one transaction for entire method insertNetJobs and inner transaction for each call updatePerson, insertPerson, insert. So the log looks like that

D/JobDao: ---- insert page start
D/SQLiteDatabase: beginTransaction() 
D/SQLiteDatabase: endTransaction()
                  beginTransaction()
D/SQLiteDatabase: endTransaction()
                  beginTransaction()
D/SQLiteDatabase: endTransaction()
                  beginTransaction()
........................
D/SQLiteDatabase: endTransaction()
                  beginTransaction()
D/SQLiteDatabase: endTransaction()
                  beginTransaction()
D/SQLiteDatabase: endTransaction()
D/JobDao: ---- insert page end

As the result the method insertNetJobs works very slow. Is there any possibility to run this method using the only one transaction?

Upvotes: 2

Views: 2284

Answers (2)

sim
sim

Reputation: 786

Ok I figured out what is the problem. In case somebody has a similar problem here is an explanation. Actual problem was with the update query. It took about 20ms to execute it.

This code:

   @Update
   public abstract int updatePerson( Person p );

Generates the following query:

UPDATE OR ABORT `sw_person` SET `id` = ?,`id_s` = ?,`id_lang` = ?,`name` = ? WHERE `id` = ?

This query updates the pk of the person's table but in the other tables this key is used as a fk which causes to look up among those tables. It's a pity that "room" updates pk in update query, probably the solutions is to write query manually.

Upvotes: 2

insa_c
insa_c

Reputation: 2931

Try this

  roomDB.runInTransaction(new Runnable() {
        @Override
        public void run() {
            Timber.d("--- insert page start");
            for( NetJob j : list ) {
                if ( updatePerson( j.getPerson() ) == 0 ) {
                    insertPerson( j.getPerson() );
                }

                insert( j.getJob() );
            } 
             Timber.d("--- insert page end");
        }
    });

Upvotes: 1

Related Questions