这是插入代码:
public voID insertOrIgnore(ContentValues values) { sqliteDatabase db = this.dbHelper.getWritableDatabase(); try { //I added these null value checks to stop NPE,but doesn't help. if (values != null && db != null) { db.insertWithOnConflict(table,null,values,sqliteDatabase.CONFliCT_IGnorE); } } catch (sqliteException e) { } finally { if (db != null) { db.close(); } }}
哪里
public static final String table = "albums";
大多数情况下,此代码使用按预期添加到数据库的数据.但是,它有时很少产生以下错误.堆栈跟踪来自ACRA,我无法隔离此错误发生的条件.我正在寻找指示为什么会发生这种情况以及条件是什么.我对sqlite的了解是初学者的.
java.lang.NullPointerException at androID.database.sqlite.sqliteStatement.releaseAndUnlock(sqliteStatement.java:290) at androID.database.sqlite.sqliteStatement.executeUpdateDelete(sqliteStatement.java:96) at androID.database.sqlite.sqliteDatabase.executesql(sqliteDatabase.java:2025) at androID.database.sqlite.sqliteDatabase.execsql(sqliteDatabase.java:1965) at androID.database.sqlite.sqliteDatabase.beginTransaction(sqliteDatabase.java:690) at androID.database.sqlite.sqliteDatabase.beginTransactionNonExclusive(sqliteDatabase.java:605) at androID.database.sqlite.sqliteStatement.acquireAndLock(sqliteStatement.java:247) at androID.database.sqlite.sqliteStatement.executeInsert(sqliteStatement.java:112) at androID.database.sqlite.sqliteDatabase.insertWithOnConflict(sqliteDatabase.java:1844) at com.mydomain.myapp.albums.AlbumsData.insertOrIgnore(AlbumsData.java:89)
第89行是上面显示的db.insertWithOnConflict(…)调用.
我不是在寻找一个完整代码的答案,而是一个指针和解释什么是错误的,所以我可以自己开始修复它.
编辑:
堆栈跟踪显示NPE源自SQLiteStatement的第290行(v 4.03):
setNativeHandle(mDatabase.mNativeHandle);
所以似乎数据库实例为null.当我在事务开始时测试null时,它如何在事务期间变为空?
解决方法 正如这里提到的 SQLiteDatabase close() function causing NullPointerException when multiple threads您的错误原因可能是您在某个时刻关闭了数据库.可能同时失败的任务没有完成.
我跟踪了堆栈跟踪,这是大致发生的事情:
> AlbumsData.insertOrIgnore(AlbumsData.java:89)
您调用insertWithOnConflict,它构建生成的sql字符串(“INSERT OR IGnorE INTO …”),然后将其与ContentValues中的值一起包装到sqliteStatement中.
> sqliteDatabase.insertWithOnConflict(sqliteDatabase.java:1844) – 生成的语句现在将被执行
> sqliteStatement.executeInsert(sqliteStatement.java:112) – 在实际插入发生之前,数据库需要获取锁.
> sqliteStatement.acquireAndLock(sqliteStatement.java:247) – 这里发生了一些检查,数据库对象就此而言在那时我看不到null.代码决定它必须启动一个事务.数据库对象本身就是我看不到的那一点.
> sqliteDatabase.beginTransactionNonExclusive(sqliteDatabase.java:605) – 只是转发
> sqliteDatabase.beginTransaction(sqliteDatabase.java:690) – 经过一些检查(不确定数据库是否必须存在),它将尝试执行execsql(“BEGIN IMMEDIATE;”)
> sqliteDatabase.execsql(sqliteDatabase.java:1965) – 只需转发
> sqliteDatabase.executesql(sqliteDatabase.java:2025) – 从“BEGIN IMMEDIATE”开始构建另一个sqliteStatement;这个应该立即执行
> sqliteStatement.executeUpdateDelete(sqliteStatement.java:96) – 从检查数据库锁开始,这似乎没问题,数据库不应该为null.然后执行该语句,最后再次解锁数据库.
> sqliteStatement.releaseAndUnlock(sqliteStatement.java:290) – 清理一些东西,最后因NPE而失败,因为数据库为空.
行号不匹配,因此该代码中可能有供应商修改/添加.
如您所见,代码在实际使用您提供的数据之前崩溃.它即将要做
BEGIN TRANSACTION IMMEDIATE; -- crashINSERT INTO table (...) VALUES (...);-- (end transaction)
这在我看来是一个框架错误.在那里内部处理的数据库对象不应该在某个地方是空的,特别是当它似乎在堆栈中没有进一步为空时.
我也认为另一个隐藏的异常可能是导致此问题的根本原因.代码中有很多try {/ * do stuff * /}最后{/ *清理* /}块,即使try部分抛出异常,也会执行finally部分.现在finally块可能导致另一个异常,结果是AFAIK,原始异常被finally块中的新异常替换.
特别是executeUpdateDelete()就像
try { acquireAndLock(WRITE); // actual statement execution} finally { releaseAndUnlock();}
如果数据库在此时关闭,则acquireAndLock或try部分中的任何代码都可能失败,这可能使数据库对象保持为null,从而导致releaseAndUnlock再次失败.你应该得到相同的堆栈跟踪.
除此之外,不要像catch(sqliteException e){/ * empty * /}那样执行空的catch块.如果可能,请使用ACRA记录它们/您不要这样做.
总结以上是内存溢出为你收集整理的android – 将数据插入SQLite时间歇性NPE全部内容,希望文章能够帮你解决android – 将数据插入SQLite时间歇性NPE所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)