我所看到的Android SQLite事务的代码示例似乎在db.endTransaction()
之前自动调用db.setTransactionSuccessful()
。
我想知道这是否是最佳实践,或者在调用db.setTransactionSuccessful()
之前是否应该进行一些条件检查。
在我的例子中,我正在覆盖ContentProvider
的bulkInsert()
方法,如果我使用所描述的条件检查,我的方法将如下所示...
@Override
public int bulkInsert(Uri uri, ContentValues[] valuesArray) {
// Open a read / write database to support the transaction.
SQLiteDatabase db = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case BRANDS_SEARCH:
int numInserts = 0;
db.beginTransaction();
for (int i = 0; i < valuesArray.length; i++) {
// Insert the values into the table
long rowId = db.insert(BRAND_NAMES_TABLE, null, valuesArray[i]);
if (rowId > -1) {
// Increment numInserts
numInserts++;
// Construct the URI of the newly inserted row.
Uri insertedId = ContentUris.withAppendedId(CONTENT_URI_BRANDS, rowId);
// Notify any observers of the change in the data set.
getContext().getContentResolver().notifyChange(insertedId, null);
}
}
boolean allInsertAttemptsWereSuccessful = (numInserts == valuesArray.length);
if (allInsertAttemptsWereSuccessful) {
db.setTransactionSuccessful(); //todo - should this be conditional?
}
else {
//todo - ???
}
db.endTransaction();
return numInserts;
default:
//break;
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
......这是正确的方法吗?
在allInsertAttemptsWereSuccessful
== false
?的情况下,我应该采取什么操作?
(我看过Android文档,但提供的信息很少。)
更新-新代码...
感谢laalto's answer,这是我的新(正确)代码...
/**
* Attempts a bulk insert. Outcome will either be all inserts succeeded
* or all inserts failed.
*/
@Override
public int bulkInsert(Uri uri, ContentValues[] valuesArray) {
/*
* Open a read / write database to support the transaction.
*/
SQLiteDatabase db = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case BRANDS_SEARCH:
/*
* Begin the transaction
*/
db.beginTransaction();
try {
for (int i = 0; i < valuesArray.length; i++) {
/*
* Insert the values into the table
*/
long rowId = db.insert(BRAND_NAMES_TABLE, null, valuesArray[i]);
if (rowId > -1) {
/*
* Construct the URI of the newly inserted row.
*/
Uri insertedId = ContentUris.withAppendedId(CONTENT_URI_BRANDS, rowId);
/*
* Notify any observers of the change in the data set.
*/
getContext().getContentResolver().notifyChange(insertedId, null);
}
else {
/*
* Give up (as we need all insert attempts to succeed)
*/
throw new Exception("Could not insert row");
}
}
/*
* All insert attempts succeeded
*/
db.setTransactionSuccessful();
return valuesArray.length;
}
catch(Exception e) {
/*
* If any insert attempt failed, then setTransactionSuccessful() will not be called so no rows will actually be inserted
*/
return 0;
}
finally {
/*
* Always end the transaction
*/
db.endTransaction();
}
default:
//break;
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
4条答案
按热度按时间new9mtju1#
事务的规范模式:
这确保了
endTransaction()
总是被调用(没有悬空事务留下),并且当某个数据库操作中发生异常时,事务会被回滚。如果你因为自己的原因想中止事务,就不要调用setTransactionSuccessful()
,或者抛出异常。tuwxkamq2#
通常,setTransactionSuccessful在endTransaction之前完成。
您也可以在对事务执行完所有数据库操作之后调用。但是这样可能就没有任何逻辑原因延迟endTransaction了。这取决于您的逻辑。如果您想确保在将更改提交到数据库之前Java代码的某个部分应该成功执行,您可以将setTransactionSuccessful和endTransaction进一步下移。
如果在startTransaction和endTransation之间编写的逻辑中出现任何异常,则可能以打开事务和饥饿结束(从您的代码中可以清楚地看到dbHelper是成员变量,因此您将在所有内容提供程序调用中使用相同的dbHelper)。相同的dbHelper示例意味着相同的SqliteDatabase示例。
因此,您必须添加try catch并在finally中结束事务。
ttisahbt3#
不需要检查
db.setTransactionSuccessful()
的条件。在插入语句之后,我们可以编写db.setTransactionSuccessful()
语句。它将处理事务。样本代码:
zc0qhyus4#
这些方法现在已弃用,因此可以使用以下代码片段: