如何在内容提供者中处理 SQLiteConstraintException
How to handle SQLiteConstraintException inside a content provider
我正在使用内容提供程序 read/write 来自允许用户组织处方的数据库。目前,我正在实现一个允许用户输入新药物的 DialogFragment。该对话框包含两个 EditText,一个用于强度,一个用于药物名称。
table 被设计成 (name, strength) 是一个唯一的键。这是我的插入方法:
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 打印异常,但调试器没有命中这些断点。
而不是抛出异常,return null
作为您的 Uri
- 然后您可以检查 insert()
调用的结果 - 如果您得到 null
return 值,你知道这是一个约束问题。
在尝试了 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();
}
我正在使用内容提供程序 read/write 来自允许用户组织处方的数据库。目前,我正在实现一个允许用户输入新药物的 DialogFragment。该对话框包含两个 EditText,一个用于强度,一个用于药物名称。
table 被设计成 (name, strength) 是一个唯一的键。这是我的插入方法:
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 打印异常,但调试器没有命中这些断点。
而不是抛出异常,return null
作为您的 Uri
- 然后您可以检查 insert()
调用的结果 - 如果您得到 null
return 值,你知道这是一个约束问题。
在尝试了 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();
}