【问题标题】:Why does my exception handler not trap Android SQLite insert error?为什么我的异常处理程序不捕获 Android SQLite 插入错误?
【发布时间】:2013-01-27 05:07:38
【问题描述】:

我是第一次使用 SQLite,并且正在尝试学习它的异常处理,所以我在我的测试应用程序中强制插入错误。发生异常,我看到它已写入 Eclipse LogCat 输出窗口。但是它不会被代码捕获。我在这里看到了关于确保使用正确的异常类型的其他问题,并认为我做对了。知道我错过了什么吗?

在我的主要活动中的以下语句中,myTable 是一个扩展我自己的AbstractDbAdapter 的类(它有一个扩展SQLiteOpenHelper 的类DatabaseHelper)。

try {
    myTable.create("dupkey");
}
catch (android.database.sqlite.SQLiteConstraintException e) {
    Log.e(TAG, "SQLiteConstraintException:" + e.getMessage());
}
catch (android.database.sqlite.SQLiteException e) {
    Log.e(TAG, "SQLiteException:" + e.getMessage());
} 
catch (Exception e) {
    Log.e(TAG, "Exception:" + e.getMessage());
}

示例堆栈跟踪:

Error inserting id="dupkey" last_seen_ts=1360624732 first_seen_ts=1360624732 android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
  at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
  at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:61)
  at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1582)
  at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1426)
  at com.myCompany.testApp.myTable_DbAdapter.create(myTable_DbAdapter.java:51)

myTableAbstractDbAdapter 类:

公共类 myTable_DbAdapter 扩展 AbstractDbAdapter { 私有静态最终字符串 DATABASE_TABLE = "myTable"; // 列名 -- ContentValues() 的键 公共静态最终字符串 KEY_ID = "id"; 公共静态最终字符串 KEY_FIRST_SEEN = "first_seen_ts"; 公共静态最终字符串 KEY_LAST_SEEN = "last_seen_ts"; 公共 myTable_DbAdapter(上下文 ctx){ 超级(ctx); } 公共长创建(字符串ID){ long firstSeen = System.currentTimeMillis() / 1000; // SQLite 时间戳以秒为单位 内容值参数 = 新的内容值(); args.put(KEY_ID, id); args.put(KEY_FIRST_SEEN, firstSeen); args.put(KEY_LAST_SEEN, firstSeen); // 默认为 firstSeen 用于新条目 返回 mDb.insert(DATABASE_TABLE, null, args); } } 公共抽象类 AbstractDbAdapter { protected static final String TAG = "AbstractDbAdapter"; 受保护的 DatabaseHelper mDbHelper = null; 受保护的 SQLiteDatabase mDb = null; 受保护的静态最终字符串 TABLE_CREATE_MYTABLE = "创建表我的表(" + " id text 主键不为空" + ", first_seen_ts 整数不为空" + ", last_seen_ts 整数不为空" + ");"; protected static final String DATABASE_NAME = "myDB"; 受保护的静态最终 int DATABASE_VERSION = 1; 受保护的最终上下文 mCtx; 受保护的静态类 DatabaseHelper 扩展 SQLiteOpenHelper { DatabaseHelper(上下文上下文){ 超级(上下文,DATABASE_NAME,空,DATABASE_VERSION); } @Override 公共无效onCreate(SQLiteDatabase db){ // 注意:SQLite 每个表需要一个 execSQL db.execSQL(TABLE_CREATE_MYTABLE); } @Override 公共无效 onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){ Log.w(TAG, "将数据库从版本" + oldVersion + "升级到" + newVersion + ",破坏现有数据。"); db.execSQL("如果存在 myTable 则删除表"); onCreate(db); } } 公共 AbstractDbAdapter(上下文 ctx){ 这个.mCtx = ctx; } 公共 AbstractDbAdapter open() 抛出 SQLException { mDbHelper = 新的数据库助手(mCtx); mDb = mDbHelper.getWritableDatabase(); 返回这个; } 公共无效关闭(){ 如果(mDb!= null){ mDb.close(); mDb = 空; } 如果(mDbHelper!= null){ mDbHelper.close(); mDbHelper = null; } } }

【问题讨论】:

  • 请贴出myTable_DbAdapter.create() 的代码并注明第51 行的位置。另外,什么类和方法包含您提供的代码?
  • @Code-Guru:我添加了 myTable 类,第 51 行是 create() 方法(它不会与堆栈跟踪完全对齐,因为我删除了一些东西来简化它这个问题)。
  • @Alan 那么您可能删除了一些可以帮助我们回答您的问题的内容。请提供完整的堆栈跟踪。
  • @Code-Guru:我从 myTable 类代码中删除了几个在本示例中未使用的方法,堆栈跟踪是从 LogCat 窗口复制的。

标签: android sqlite exception-handling


【解决方案1】:

我在这里找到了答案:SQLiteConstraintException not caught

SQLiteDatabase.insert() 方法不会抛出异常。哦!

对于像我这样的其他 SQLite 新手,如果您想在插入数据库时​​捕获异常,请使用 SQLite.insertOrThrow() 方法。它会抛出一个异常,然后你可以捕获并处理它。

【讨论】:

  • 已确认:通过将 myTable_DbAdapter 类更改为使用 insertOrThrow(),我现在在我的测试应用程序中遇到可捕获的错误,并且在 LogCat 输出中只看到一行“SQLiteConstraintException:错误代码 19:约束失败”完整的堆栈跟踪。
  • 不要忘记在你的 Android 应用中打开数据库后立即添加以下代码:db.execSQL("PRAGMA foreign_keys=ON");这将打开对外键的支持,这是 ON DELETE CASCADE 正常工作所必需的。
  • 我在 react-native(github.com/andpor/react-native-sqlite-storage) 中使用 sqlite。我该如何处理?我找不到类似的方法
  • @SureshPrajapati 好问题,如果你找到答案,请告诉我!
【解决方案2】:

虽然不是 100% 与该问题相关,但我在使用 Room 时遇到了类似的问题,Google 为我的搜索返回了这个问题。在 Room 的情况下,似乎没有抛出可捕获的异常,并且 insertOrThrow() 不存在。在查看https://developer.android.com/reference/kotlin/androidx/room/OnConflictStrategy#ABORT:kotlin.Int 时,许多选项都已贬值,但我在这里选择了 OnConflictStrategy.IGNORE,因为如果出现问题,它将返回 -1。

干杯。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 2017-05-02
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多