10
So I’m facing some problems with my Sqlite connection, where I’m not finding a skilled solution.
Setting
My scenario is this::
- I synchronize the data of my application with a legacy system, through a Webservice;
- This synchronization is done through a Thread that checks what’s new in the legacy database and starts several other Threads to get the data and save it in its local base (Sqlite);
- For each entity that is found new data in the legacy database a new Thread is opened, (each entity has an Endpoint, where it is accessed, downloaded, and saved the data, and then finalized the Thread). Ex: if there are new clients in the legacy database, a request is started that will fetch all new clients, and saves them in my client table in Sqlite, this would run in a Thread;
Problem
The problem is that even if I use AsyncTask.SERIAL_EXECUTOR
that only runs one Thread at a time, between an opening and another connection ends up generating problem Lock, where I cannot get the Current reference of the connection and when trying to create a new one it accuses that db is Locked.
I believe my problem is not even with threads running simultaneously, but in my class
connection management, which I am currently using is:
public abstract class GConexaoAdapter {
private final DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
protected final Context ctx;
public GConexaoAdapter(Context ctx, String dbName, int dbVersion) {
this.mDbHelper = new DatabaseHelper(ctx, dbName, dbVersion);
this.ctx = ctx;
}
private void open() {
try {
synchronized (ctx) {
synchronized (mDbHelper) {
if (mDb == null) {
mDb = mDbHelper.getWritableDatabase();
} else {
synchronized (mDb) {
mDb = mDbHelper.getWritableDatabase();
}
}
}
}
} catch (IllegalStateException e) {
e.printStackTrace();
if (mDb == null || !mDb.isOpen())
mDb = ctx.openOrCreateDatabase(mDbHelper.getDatabaseName(), 0,
null);
Log.i("TRATAR", "tratar");
}
}
protected SQLiteDatabase getConexao() {
synchronized (ctx) {
synchronized (mDbHelper) {
if (mDb == null) {
this.open();
} else if (!mDb.isOpen()) {
synchronized (mDb) {
if (!mDb.isOpen()) {
this.open();
}
}
}
return mDb;
}
}
}
protected void closeConexao() {
synchronized (ctx) {
synchronized (mDbHelper) {
if (mDb != null && mDb.isOpen()) {
synchronized (mDb) {
if (mDb.isOpen()) {
if (mDb.inTransaction()) {
mDb.endTransaction();
}
mDb.close();
}
}
}
}
}
}
private static class DatabaseHelper extends SQLiteOpenHelper {
@Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
if (!db.isReadOnly()) {
// db.execSQL("PRAGMA foreign_keys=ON;");
}
}
DatabaseHelper(Context context, String dbNome, int dbVersion) {
super(context, dbNome, null, dbVersion);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
}
I don’t think I need all the synchronized
that I have, is that I have tried several solutions I have found and none brought me the expected result.
Question?
I believe there’s even a "Cake recipe" for this type of connection management. I may not be the only one who needs a solution like this.
So how would I manage to effectively, effectively manage my connection to the Sqlite database?
Very important remark:
I would like to manage the Sqlite connection between multiple simultaneous threads, however without causing Locks that end up generating exceptions and violating data integrity!
I understood your suggestion, and it seems useful, but connection management should not be restricted to threads but to any connection call. I believe I could control the connection by keeping a single instance in the object Gconexaoadapter, I’m just looking for a way to do it well. I’m working in that idea
– Fernando Leal
In any access to the bank you will have to use the
synchronized()
to avoid competing calls togetWritableDatabase()
. You can’t do it any other way. The only alternative would be to create methodsinsert()
,delete()
, etc. in theGConexaoAdapter
, all of themsynchronized
, and within each you callgetWritableDatabase()
before executing the operation itself, andclose()
next.– Piovezan
"to avoid competing calls to getWritableDatabase()" - read "to ensure the atomic operation composed of
mDb = mDbHelper.getWritableDatabase()
andmDb.close()
"– Piovezan
your answer helped me find the path of stones, check out my solution.
– Fernando Leal