我想將行插入Android內的SQLite數據庫。將記錄插入我的數據庫的調用如下所示:DataHelper.insertChild(context,child)。我的目標是將這些功能封裝到靜態調用的函數中,以處理所有的細節。首先讓我與你分享我的代碼。Android SQLiteStatement插入;後續調用失敗
我通過靜態方法這樣做:
private static SQLiteDatabase prepareChildDatabase(Context context) {
Log.d(TAG, "DB: prepareChildDatabase");
OpenHelper openHelper = new OpenHelper(context);
return openHelper.getWritableDatabase();
}
然後,我做我的插入:
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;
}
對於引用,我OpenHelper是在這裏:
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);
}
}
最後,變量,陳述和表格:
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)";
所以發生的事情是,我第一次稱此爲一切正常。插入工作,數據在那裏,我可以將數據庫從設備導出到我的SQLite瀏覽器。隨後調用insertChild(...)會中斷數據庫。打開不起作用,SQLiteBrowser不顯示任何表或行,並在文本編輯器中打開它顯示一些內容;我的猜測是數據庫已損壞。沒有更多行正在插入,我無法讀取它。 沒有任何錯誤拋出。
我猜這是兩件事情之一。首先,我的手柄沒有正確打開/關閉,某些參考文件正在被隨後的調用取代。其次,我對準備好的陳述的理解是錯誤的。事情是,我看看代碼,它似乎很好。打開數據庫,綁定到準備好的語句,執行,關閉語句,關閉數據庫。
有人願意幫我解決這個問題嗎?我一直在記錄日誌,尋找異常,嘗試東西,但似乎沒有任何工作。我想我可能只是錯過了一些細節。這或我瘋了。
感謝,
邁克
更新
我已經把我的注意力轉向線程,因爲這個問題並不在我的模擬器重現。看看這些鏈接:
http://www.kagii.com/journal/2010/9/10/android-sqlite-locking.html
android sqlite application is being forcefully closed on device
What are the best practices for SQLite on Android?
是的,每次我插入我調用getWritableDatabase()應該「創建和/或打開將用於讀取和寫入的數據庫」。根據文件。這些插入很少被調用,所以我可以打開和關閉每個DB的數據庫。看看我的函數prepareDatabase(...)。它在函數的開始處被調用,並將打開一個連接。 – mhradek 2011-03-28 21:24:28
prepareChildDatabase和prepareDatabase是一樣的嗎? – 2011-03-29 13:20:30
是的,我忘了添加孩子來清理事情。編輯。 – mhradek 2011-03-29 16:28:11