Problem with multithreaded inserts

467 views
Skip to first unread message

georgie...@gmail.com

unread,
Jan 10, 2011, 5:16:36 AM1/10/11
to ORMLite Users


I get this error while making inserts with +3 threads.

General Pattern is:

public abstract class CommonDb extends
OrmLiteBaseActivity<DatabaseHelper> {
DatabaseHelper one;
AtomicInteger clientCount = new AtomicInteger();

static {
OpenHelperManager.setOpenHelperFactory(new SqliteOpenHelperFactory()
{
public OrmLiteSqliteOpenHelper getHelper(Context context) {
return new DatabaseHelper(context);
}

});
}

synchronized DatabaseHelper GetHelper() {

clientCount.getAndIncrement();
if (one == null)
one = getHelper();
return one;
}

synchronized void closeHelper(DatabaseHelper helper) {

int count = clientCount.decrementAndGet();
if (count == 0) {
Log.i("prototype", "oneSource closeHelper closing helper");
one.close();
}
helper.close();
}

protected class InitTask extends AsyncTask<Context, Integer, String> {

@Override
protected String doInBackground(Context... params) {
handlerShowProgressBar.sendEmptyMessage(0);
try {
Thread.sleep(6000);
LoadData();
synchronized (DatabaseHelper.class) {
RecordData();
}
} catch (Exception e) {
// Log
}
return "COMPLETE!";
}

the RecordData is in the activities.

I get this error:

01-10 12:06:07.953: ERROR/Error(23196):
java.lang.IllegalStateException: you must call initialize() before you
can use the dao

Any ideas ? :)

georgie...@gmail.com

unread,
Jan 10, 2011, 5:31:51 AM1/10/11
to ORMLite Users
Hmm, strange. If I don't close the DatabaseHelper everything
works :).
Maybe this is a bug in the threading of the ORM.

Larry Hamel

unread,
Jan 10, 2011, 12:54:33 PM1/10/11
to ormlit...@googlegroups.com
I believe sqlite is serializing requests through a single connection, so having multiple helpers doesn't seem useful to me.

Consider using an Application subclass to manage a singleton handler that is threadsafe. I use something like the code below. Note that the onCreate and onUpgrade connections are special, one-time connections.

larry

-------------------------

public class AppHelper extends OrmLiteSqliteOpenHelper {
private Context context;

public AppHelper(Context context) {
super(context, DB_NAME, null, DATABASE_VERSION);
this.context = context;
}

@Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
// do initialization using db and conn source but do NOT cache them
// do NOT call getWriteableDatabase() here
}

@Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
// do initialization using db and conn source but do NOT cache them
// do NOT call getWriteableDatabase() here
}

---------------------------------

Gray Watson

unread,
Jan 10, 2011, 3:24:49 PM1/10/11
to ormlit...@googlegroups.com
I'm not an Android expert. Larry and others are more experienced with using ORMLite with Android. I do know, as Larry mentioned, that you should _only_ use one helper and one database connection -- even with multithreaded apps. Here's a great post from Kevin who wrote most of the Android fu for ORMLite.

http://kagii.squarespace.com/journal/2010/9/10/android-sqlite-locking.html

> clientCount.getAndIncrement();
> if (one == null)
> one = getHelper();

I notice that you are using AtomicInteger for the clientCount but that the DatabaseHelper one is neither AtomicReference, volatile, or synchronized. Seems like there are a number of race conditions around one and whether it has been initialized or closed.

> int count = clientCount.decrementAndGet();
> if (count == 0) {
> Log.i("prototype", "oneSource closeHelper closing helper");
> one.close();

For example, shouldn't 'one' be set to null here? What happens if it has been closed and another thread calls getHelper()?

> 01-10 12:06:07.953: ERROR/Error(23196):
> java.lang.IllegalStateException: you must call initialize() before you
> can use the dao

Can you post the entire stack trace? This indicates to me that the connectionSource has been closed in the OrmLiteSqliteOpenHelper already and it is null. Once it is null then the DAO thinks that it has not be initialized, hence the error.

gray

Reply all
Reply to author
Forward
0 new messages