2011-03-28 63 views
0

我想將行插入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?

回答

0

你應該打開總是在你需要它的連接。或者在關閉之前先將所有插入物打開。

+0

是的,每次我插入我調用getWritableDatabase()應該「創建和/或打開將用於讀取和寫入的數據庫」。根據文件。這些插入很少被調用,所以我可以打開和關閉每個DB的數據庫。看看我的函數prepareDatabase(...)。它在函數的開始處被調用,並將打開一個連接。 – mhradek 2011-03-28 21:24:28

+0

prepareChildDatabase和prepareDatabase是一樣的嗎? – 2011-03-29 13:20:30

+0

是的,我忘了添加孩子來清理事情。編輯。 – mhradek 2011-03-29 16:28:11

0

首先......當您使用數據庫實例或遊標實例或Steatment實例(或任何需要在最後關閉的對象)時,請使用以下語法;

SQLiteOpenHelper db; 
    try{ 
     db = myDB.open();//open the database here 
     //do whatever you want with the DB instance 
    }finally{ 
     if(db != null){ 
      db.close(); 
     } 
    } 

如果在進程中間引發異常,您將關閉數據庫。

刪除這最後

final long id = insertStmt.executeInsert(); 

而要調試好,放了抓在試圖/最終,你會看到更好的是怎麼回事。

+0

正在離開try/catch/finally最佳實踐,直到我更接近實現DataHelper對象。由於這個問題沒有拋出它並不能幫助我。我很好奇爲什麼我應該離開決賽。該建議不符合Java最佳實踐。它在executeInsert()的輸出中遞增得很好。 – mhradek 2011-04-06 19:05:44