2011-03-28 4 views
0

Android内のSQLiteデータベースに行を挿入しようとしています。私のDBにレコードを挿入するための呼び出しは次のようになります: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ブラウザにDBをエクスポートすることができます。その後、insertChild(...)を呼び出すと、DBが破損します。 SQLiteBrowserにテーブルや行が表示されず、テキストエディタ内で開くといくつかのことが表示されます。私の推測は、DBが壊れているということです。行が挿入されていないため、読み込めません。 何もエラーはスローされません。

私はここで2つのことの1つを推測しています。まず、私のハンドルが正しく開閉しておらず、後の呼び出しでどこかの参照がボークされています。第二に、準備された声明の私の理解は間違っています。私はコードを見て、うまくいるようです。データベースを開き、プリペアドステートメントにバインドし、実行し、ステートメントを閉じ、データベースを閉じます。

誰もがこれで私を助けてくれるのですか?私はログに記録して、例外を探して、試してみましたが、何も動かないようです。私はちょっとした細部を見逃したかもしれないと思う。それとも私は狂ってしまいます。

おかげで、

マイク

更新

問題は私のエミュレータ上で再現していないので、私は、スレッドの方に私の注意を向けてきました。これらのリンクをチェックアウト:

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

私がテストしているデバイスには、アクセス許可とデータベースファイルの書き込みに問題があるようです。問題は実際には、DBが最初に作成され、行が挿入され、ロックされていることです。その後の呼び出しで破損します。

これはおそらく、デバイスを応援した結果です。または、パッケージのUIDが変更されたためです。

0

あなたは、あなたがそれを必要と常に接続を開く必要があります。または、すべての挿入を行う前に開いてから閉じてください。

+0

はい、挿入するたびに「読み書きに使用されるデータベースを作成および/または開く」というgetWritableDatabase()を呼び出します。ドキュメントに従って。これらの挿入はめったに呼び出されないので、DBを開いたり閉じたりするのは大丈夫です。私の関数prepareDatabase(...)を見てください。関数の開始時に呼び出され、接続を開きます。 – mhradek

+0

prepareChildDatabaseとprepareDatabaseは同じですか? –

+0

はい、私は物事をクリアするために子供を追加することを忘れました。編集されました。 – mhradek

0

まず、DBインスタンス、カーソルインスタンス、または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(); 
     } 
    } 

あなたはDBを閉じます。

この最終

final long id = insertStmt.executeInsert(); 

を削除して、より良いデバッグし、最後に/試してみて、あなたは何が起こっているのか良くわかりますようにキャッチを置きます。

+0

は、DataHelperオブジェクトの実装に近づくまで、try/catch/finallyのベストプラクティスをオフにしていました。この問題は投げていないので、それは私を助けません。なぜ私が決勝戦から離れるべきか不思議です。この提案は、Javaのベストプラクティスに準拠していません。これは、executeInsert()の出力が正常にインクリメントされています。 – mhradek

関連する問題