Reputation: 786
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
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
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