I have faced your problem a few months ago and struggle against it a day or two...
Your problem is in the connections. You must not use different connections because each active connection locks the database when it uses it. If you want to execute parallel operations over the database, you can still use threads but take in mind that you must do the synchronization in your java code. You have two options for synchronization:
- java locking mechanisms:
synchronized
and locks
- SQL transactions
I advise you to use both. Use transactions everywhere you are performing DB operation (no matter if you are doing it in parallel or not). This way you will be safe from experiencing future problems with reading wrong/old/partial data. Use the java concurrent API when you are dealing with concurrent access to java objects that are related to the database (e.x: a counter that tracks the number of parallel java consumers of the database, the db helper instance, etc).
I have used the following code to manage the access to the database connection. I hope this snippet will help you solve your problems. Take in mind that this code snippet is taken from an existing project so it contains references to class name and methods that are not shown here but I hope the basic idea is clear.
/**
* Defines the supported database types of access
*/
public enum AccessType {
READABLE, WRITABLE;
}
protected static volatile SQLiteDatabase sDatabase;
private static volatile int sCounter;
private static final Object LOCK = new Object();
/**
* Opens the database for access.
*
* @param accessType
* The type of access to be used.
* @throws SQLException
* If something goes wrong.
*/
public final void open(final AccessType accessType) throws SQLException {
synchronized (LOCK) {
sCounter++;
if (sDatabase != null && sDatabase.isOpen()) {
return;
}
switch (accessType) {
case READABLE: {
sDatabase = mDBHelper.getReadableDatabase();
break;
}
case WRITABLE: {
sDatabase = mDBHelper.getWritableDatabase();
break;
}
default:
throw new IllegalArgumentException("This AccessType is not supported!");
}
}
}
/**
* Closes the database connection.
*/
public final void close() {
synchronized (LOCK) {
sCounter--;
if (sCounter == 0 && sDatabase != null && sDatabase.isOpen()) {
sDatabase.close();
}
}
}
@Override
public final void create(final T entry) {
sDatabase.beginTransaction();
try {
doCreate(entry);
sDatabase.setTransactionSuccessful();
} finally {
sDatabase.endTransaction();
}
}