【问题标题】:How to handle SQLiteConstraintException inside a content provider如何在内容提供程序中处理 SQLiteConstraintException
【发布时间】:2015-01-20 21:20:57
【问题描述】:

我正在使用内容提供程序从允许用户组织处方的数据库中读取/写入。目前,我正在实现一个允许用户输入新药物的 DialogFragment。该对话框包含两个 EditText,一个用于强度,一个用于药物名称。

该表的设计使(名称,强度)是唯一的键。这是我的插入方法:

public Uri insert(Uri uri, ContentValues values) {
    final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
    final int match = sUriMatcher.match(uri);
    long _id; // Value used for inserts.
    Uri returnUri;

    switch(match){
        case MEDICATION:
            _id = db.insert(PMContract.MedicationEntry.TABLE_NAME, null, values);
            if(_id > 0)
                returnUri = PMContract.MedicationEntry.buildMedicationUri(_id);
            else
                throw new UnsupportedOperationException("Failed to insert row into: " + uri);
            break;
        default:
            throw new UnsupportedOperationException("Unknown uri: " + uri);
    }

如您所料,如果用户输入了已经存在的名称和强度,则会发生 SQLiteConstraintException。但是,我在这里所做的只是抛出一个 UnsupportedOperationException,这是我从内容提供程序教程中学到的。

我想做的是专门处理输入重复键的情况,以便我可以将该信息传递给用户(可能通过 Toast)。

我尝试在我进行插入调用的位置添加一个 try/catch:

try{
    getActivity().getContentResolver().insert(PMContract.MedicationEntry.CONTENT_URI, values);
} catch(SQLiteConstraintException e){
}

但是捕获的不是 SQLiteConstraintException,而是 UnsupportedOperationException。

如何调整 ContentProvider 代码,以便知道何时出现 ConstraintException,并将其他所有内容视为 UnsupportedOperationException?

编辑

我试图在 db.insert 调用周围包裹一个 try/catch 块:

case MEDICATION:
    try {
        _id = db.insert(PMContract.MedicationEntry.TABLE_NAME, null, values);
    } catch(SQLiteConstraintException e){
        String s = e.getMessage();
    } catch(Exception e1){
        String s1 = e1.getMessage();
    }

    if(_id > 0)
        returnUri = PMContract.MedicationEntry.buildMedicationUri(_id);
    else
        throw new UnsupportedOperationException("Failed to insert row into: " + uri);
    break;

我使用调试器查看了db.insert() 引发的异常。但是,调试器没有在 任何一个 的 catch 块中命中断点,即使在 logcat 中打印了错误文本。我不确定为什么会向 logcat 打印异常但调试器没有命中这些断点。

【问题讨论】:

    标签: java android try-catch android-sqlite


    【解决方案1】:

    不要抛出异常,而是将null 作为您的Uri 返回-然后您可以检查insert() 调用的结果-如果您得到null 返回值,您就知道这是一个约束问题。

    【讨论】:

    • 我想过类似的事情,但如果我有一个空 Uri,它仍然可能是 any SQLiteException,不是吗?
    • 不,只在 insert() 方法中捕获 SQLiteConstraintException 并仅在这些情况下返回 null
    • 嗯,我似乎无法捕捉到异常。我在问题中添加了一个小代码 sn-p 来演示我的尝试。
    【解决方案2】:

    在尝试了 Ian 的建议并编辑了我的问题后,我意识到我遇到了与 question 相同的问题。

    将代码行更改为 db.insertOrThrow() 会导致 ConstraintException 在发生时被抛出,并且我能够在 DialogFragment 中捕获它:

    // In the ContentProvider
    _id = db.insertOrThrow(PMContract.MedicationEntry.TABLE_NAME, null, values);
    
    // In the Dialog Fragment
    try{
        getActivity().getContentResolver().insert(PMContract.MedicationEntry.CONTENT_URI, values);
        dismiss();
    } catch(SQLiteConstraintException e){
        Toast.makeText(getActivity(), "A medication with this name and strength already exists.", Toast.LENGTH_SHORT).show();
    } catch(UnsupportedOperationException uoe){
        Toast.makeText(getActivity(), "Unable to insert new medication.", Toast.LENGTH_SHORT).show();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多