如何在内容提供程序中处理SQLiteConstraintException

时间:2015-01-20 21:20:58

标签: java android try-catch android-sqlite

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

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

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()引发的异常。但是,即使错误文本打印在logcat中,调试器也没有在catch块的 中遇到断点。我不确定为什么会向logcat打印异常,但调试器不会触及这些断点。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

在尝试了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();
}