我正在尝试在Android中的SQLite数据库中插入行。将记录插入我的数据库的调用如下所示:DataHelper.insertChild(context,child)。我的目标是将功能包装到静态调用的函数中,以处理所有细节。首先让我与您分享我的代码。
我是通过静态方法做到的:
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(...)的后续调用会破坏DB。打开不起作用,SQLiteBrowser不显示任何表或行,并在文本编辑器中打开它显示一些东西;我的猜测是数据库已损坏。没有更多的行被插入,我无法读取它。 不会抛出任何错误。
我猜这里发生了两件事之一。首先,我的句柄没有正确打开/关闭,某些地方的引用被随后的调用搞砸了。其次,我对准备好的陈述的理解是错误的。问题是我看代码,看起来很好。打开数据库,绑定到预准备语句,执行,关闭语句,关闭数据库。
有谁愿意帮我解决这个问题?我一直在记录,寻找异常,并尝试一些东西,但似乎没有任何工作。我想我可能只是错过了一些细节。那或我疯了。
谢谢,
麦克
更新
我已将注意力转向线程,因为问题不会在我的模拟器上重现。看看这些链接:
http://www.kagii.com/journal/2010/9/10/android-sqlite-locking.html
android sqlite application is being forcefully closed on device
答案 0 :(得分:0)
您应该始终打开连接。或者在关闭它之前打开所有插入之前打开它。
答案 1 :(得分: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();
为了更好地调试,在try / finally中加入一个catch,你会看到更好的结果。
答案 2 :(得分:0)
我正在测试的设备似乎存在权限问题和编写数据库文件。问题实际上是DB最初创建,插入行,然后它被锁定。后续调用会破坏它。
这可能是设备生根的结果。或者可能因为包UID已更改。