I am trying to insert rows into a SQLite database within Android. A call to insert a record into my DB looks like this: DataHelper.insertChild(context, child). My goal is to wrap the functionality into statically called functions that handle all the nitty gritty. First let me share with you my code.
I am doing this via static methods:
private static SQLiteDatabase prepareChildDatabase(Context context) {
Log.d(TAG, "DB: prepareChildDatabase");
OpenHelper openHelper = new OpenHelper(context);
return openHelper.getWritableDatabase();
}
Then I do my insert:
public static long insertChild(Context context, Child child) {
Log.d(TAG, "DB: insertChild");
SQLiteDatabase db = prepareChildDatabase(context);
SQLiteStatement insertStmt = db.compileStatement(INSERT);
insertStmt.bindLong(1, child.getBirthday().getTime());
// These are optional
if(child.getName() != null) {
insertStmt.bindString(2, child.getName());
} else {
insertStmt.bindNull(2);
}
if(child.getPhoto() != null) {
String photoUri = child.getPhoto().toString();
insertStmt.bindString(3, photoUri);
} else {
insertStmt.bindNull(3);
}
final long id = insertStmt.executeInsert();
// insertStmt.clearBindings(); // Not sure this is necessary
insertStmt.close();
db.close();
return id;
}
For references, my OpenHelper is here:
private static class OpenHelper extends SQLiteOpenHelper {
OpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.d(TAG, "DB: OpenHelper: onCreate: " + CREATE_CHILDREN_TABLE);
db.execSQL(CREATE_CHILDREN_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
And finally, the variables, statements, and table:
private static final String TABLE_NAME = "children";
private static final String COL_NAME = "name";
private static final String COL_BDAY = "birthday";
private static final String COL_PHOTO = "photo";
private static final String INSERT = "insert into "
+ TABLE_NAME + " ("
+ COL_BDAY + ", "
+ COL_NAME + ", "
+ COL_PHOTO + ") values (?, ?, ?)";
private static final String UPDATE = "update "
+ TABLE_NAME + "set "
+ COL_BDAY + " = ?, "
+ COL_NAME + " = ?, "
+ COL_PHOTO + " = ?) WHERE "
+ BaseColumns._ID + " = ?";
private static final String CREATE_CHILDREN_TABLE =
"CREATE TABLE " + TABLE_NAME + " ("
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ COL_BDAY + " INTEGER NOT NULL, "
+ COL_NAME + " TEXT NULL, "
+ COL_PHOTO + " TEXT NULL)";
So what is happening is that the first time I call this everything works fine. Insert works, data is there, and I can export the DB from the device to my SQLite browser. Subsequent calls to insertChild(...) break the DB. Opening doesn't work in that SQLiteBrowser shows no tables or rows and opening it within a text editor shows some things; my guess is that the DB is corrupted. No more rows are being inserted and I can't read it. No errors are thrown whatsoever.
I am guessing one of two things going on here. First, my handles aren't opening/closing correctly and some reference somewhere is getting borked by the subsequent calls. Second, my understanding of prepared statements is faulty. The thing is that I look at the code and it seems fine. Open a database, bind to a prepared statement, execute, close statement, close database.
Anyone out there willing to help me out with this? I've been logging, looking for exceptions, and trying things but nothing seems to work. I think I may have simply missed a little detail. That or I am going insane.
Thanks,
Mike
Update
I've turned my attention towards threads because the issue doesn't reproduce on my emulator. Check out these links:
http://www.kagii.com/journal/2010/9/10/android-sqlite-locking.html
android sqlite application is being forcefully closed on device