我们的活动包含项目列表及其状态。当用户单击该项目时,将启动另一个活动,用户可以在其中执行更改该项目状态的某些任务。当活动完成并且前一个活动恢复时,将从数据库中查询项目及其状态并列出(查询基本上执行计数(*),因此它应该找到刚刚插入的记录)。
问题是有些用户报告有时项目没有更新,所以他们回去再次执行任务导致重复交易,这在正常情况下是不可能的(我们可以从服务器上的数据。)
由于某种原因,我根本无法复制行为(在实际的设备和模拟器上)。但是我们知道由于用户反馈和我们收到的数据,查询返回旧数据。根据我的估计,它发生在大约3%的时间。
这是否与SQLite设置有关,或者我们的代码中是否有错误?
这基本上就是代码的作用:
// Insert new record
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
processContentForDeviceStock(contentValues, object);
db.insert("table", null, contentValues);
db.close();
new AlertDialog.Builder(
CurrentActivity.this)
.setTitle("Success")
.setMessage("Insert succesful")
.setPositiveButton("OK",
new OnClickListener() {
@Override
public void onClick(
DialogInterface dialog,
int which) {
setResult(RESULT_OK);
// We are done, go back to the previous activity
finish();
}
}).create().show();
当List活动恢复时:
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery(listQuery, null);
res.moveToFirst();
while(!res.isAfterLast()) {
// Build our item list
/*
...
*/
res.moveToNext();
}
res.close();
db.close();
// List the items and their statuses
/*
...
*/
还有一个后台线程在后台运行并尝试读取/更新。
对我来说,最大的问题是任何地方都没有任何错误迹象。 SQLite报告所有事务都成功,并且发生了错误,锁定或其他错误。
更新
我们在不同的应用程序中遇到了完全相同的错误。我们可以看到数据由于发送到服务器的内容而被复制,但是我们无法确定问题是数据是否未被更新或者Sqlite是否返回旧数据。我们所做的一项改变是确保只能从所有线程访问一个数据库连接。
以下是执行更新的代码:
// Validation and column index handling code omitted
public long updateOrInsertUserTransaction(ArrayList<UserTransaction> entityList) {
SQLiteDatabase db = this.getWritableDatabase();
String sql = "INSERT OR REPLACE INTO UserTransaction(UniqueId, TransType, " +
"TransSubtype, TransDate, UserId, StockId, NumericValue, StringValue, " +
"Latitude, Longitude, Accuracy, Comment, synched, deliveryattempts, firstdeliveryattempt)" +
" VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
db.beginTransaction();
SQLiteStatement stmt = db.compileStatement(sql);
for (int i = 0; i < entityList.size(); i++) {
UserTransaction entity = entityList.get(i);
stmt.bindString(0 entity.getUniqueId());
stmt.bindLong(1 entity.getTransType());
if (entity.getTransSubtype() != null)
stmt.bindLong(2, entity.getTransSubtype());
stmt.bindString(3, entity.getTransDate());
if (entity.getUserId() != null)
stmt.bindLong(4, entity.getUserId());
if (entity.getStockId() != null)
stmt.bindLong(5, entity.getStockId());
if (entity.getNumericValue() != null)
stmt.bindDouble(6, entity.getNumericValue());
String stringValue;
if ((stringValue = entity.getStringValue()) != null)
stmt.bindString(7, stringValue);
stmt.bindDouble(8, entity.getLatitude());
stmt.bindDouble(9, entity.getLongitude());
stmt.bindDouble(10, entity.getAccuracy());
if (entity.getComment() != null)
stmt.bindString(11, entity.getComment());
stmt.bindLong(12, entity.synched);
stmt.bindLong(13, entity.deliveryattempts);
if (entity.firstdeliveryattempt != null)
stmt.bindString(14, entity.firstdeliveryattempt);
stmt.execute();
stmt.clearBindings();
}
db.setTransactionSuccessful();
db.endTransaction();
// Database is closed elsewhere via a Singleton
Log.i(TAG, "updateOrInsertUserTransaction() - " + entityList.size());
return entityList.size();
}