Reputation: 886
I have an insert statement and it takes my app about 25 seconds to insert ~1000 rows. I'm trying to use Transactions
to speed up my processing time but I'm having trouble implementing it.
Here is my method for inserting
in my DatabaseHandler
:
public boolean insertQuestions(String gid, String qid, String qname) {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
try {
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_GID, gid);
contentValues.put(KEY_QID, qid);
contentValues.put(KEY_QNAME, qname);
long result = db.insert(TABLE_QUESTIONS, null, contentValues);
db.setTransactionSuccessful();
if (result == -1) {
db.close();
return false;
} else {
db.close();
return true;
}
} finally {
db.endTransaction(); //Error is here
}
}
I'm getting the following error when I try to run the above method:
08-28 15:50:40.961 20539-20539/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.murrion.navigationdrawer, PID: 20539
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /storage/emulated/0/testapp3.db
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:522)
at com.murrion.navigationdrawer.utils.DatabaseHandler.insertQuestions(DatabaseHandler.java:197)
The statement is being run in an Asynctask method in my Activity.
Upvotes: 1
Views: 5250
Reputation: 38605
Two problems
You can make a Question
class that encapsulates the data of a single question. In that case your method might look like this:
public boolean insertQuestions(List<Question> questions) {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
try {
ContentValues contentValues = new ContentValues();
for (Question question : Questions) {
contentValues.put(KEY_GID, question.gid);
contentValues.put(KEY_QID, question.qid);
contentValues.put(KEY_QNAME, question.qname);
db.insert(TABLE_QUESTIONS, null, contentValues);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
Upvotes: 4
Reputation: 12861
I think you are inserting question using insertQuestions()
one by one. So beginTransaction()
and endTransaction()
called many more times which is inefficient.
There is some changes needed to speed up transactions:
You should have to first insert all questions to array then use like:
db.beginTransaction();
for (entry : listOfQuestions) {
db.insertQuestions("","","");
}
db.setTransactionSuccessful();
db.endTransaction();
Some modifications in your method.
public boolean insertQuestions(String gid, String qid, String qname) {
SQLiteDatabase db = this.getWritableDatabase();
boolean wasSuccess = true;
try {
db.beginTransaction();
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_GID, gid);
contentValues.put(KEY_QID, qid);
contentValues.put(KEY_QNAME, qname);
long result = db.insert(TABLE_QUESTIONS, null, contentValues);
if (result == -1) {
wasSuccess = false;
} else {
db.setTransactionSuccessful();
}
} finally {
db.endTransaction();
db.close();
}
return wasSuccess;
}
I hope it helps!
Upvotes: 1
Reputation: 17150
You have already closed the db before ending the transaction, instead close it after ending.
public boolean insertQuestions(String gid, String qid, String qname) {
SQLiteDatabase db = this.getWritableDatabase();
boolean wasSuccess = true;
try {
db.beginTransaction();
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_GID, gid);
contentValues.put(KEY_QID, qid);
contentValues.put(KEY_QNAME, qname);
long result = db.insert(TABLE_QUESTIONS, null, contentValues);
if (result == -1) {
wasSuccess = false;
} else {
db.setTransactionSuccessful();
}
} finally {
db.endTransaction();
db.close();
}
return wasSuccess;
}
Upvotes: 5