Sqlite事务具有读写功能

时间:2013-12-12 17:58:48

标签: android sqlite transactions

是否可以在android中使用事务来读取稍后将在同一事务中删除的值?

这样的事情:

SQLiteDatabase db = helper.getReadableDatabase();
db.beginTransaction();

String whereClause = "COL1 = ? AND COL2 = ?";

// make a SELECT Query to read data 
Cursor c = db.rawQuery("SELECT * FROM Foo "+whereClause, whereValues);

...
// read Cursor data etc. 
...

db = helper.getWriteableDatabase();
// Delete data
db.delete("Foo", whereClause, whereValues);

db.setTransactionSuccessful();
db.endTransaction();

所以我想获取我要删除的数据,以通知UI组件数据已被删除。

我使用多个线程,并希望确保在查询和删除之间没有更改表中的其他数据。

我可以在带有同步等的java中执行此操作或锁定整个数据库(我只会将其作为最后一个选项)。

那么是否有可能并保存为此用例使用事务?如果是,如何在写入和读取事务中使用getWriteableDatabase()和getReadableDatabase()?

使用事务是否保证将删除之前已查询的数据?并且不可能在SELECT查询和DELETE之间插入另一个datarecord(例如由另一个Thread)...我想避免删除前一个SELECT查询尚未查询的数据记录(因为它已经在SELECT查询之后和DELETE语句之前插入了)

示例:我有一个名为Foo的表:

 ID | COL1 | COL2
 ---|------|-----  
  1 |  1   |   1
 ---|------|-----
  2 |  0   |   1
 ---|------|-----
  3 |  1   |   1

让我们假设我使用交易方法: 我会执行SELECT * FROM Foo WHERE COL1 = 1 AND COL2 = 1。结果我将得到ID = 1且ID = 3的行。

让我们假设现在,在执行DELETE statemet之前,另一个Thread已插入一行,以便表格如下所示:

 ID | COL1 | COL2
 ---|------|-----
  1 |  1   |   1
 ---|------|-----
  2 |  0   |   1
 ---|------|-----
  3 |  1   |   1
 ---|------|-----
  4 |  1   |   1

接下来将执行DELETE语句:DELETE FROM Foo WHERE COL1 = 1 AND COL2 = 1

因此删除ID = 1,ID = 3和ID = 4的行。

但前一个SELECT的结果集是ID = 1且ID = 3的行。 所以我丢失了ID = 4的行而没有注意到。

这正是我想要避免的。

我想这将是LOCK的用例,但我不喜欢LOCKS ......

2 个答案:

答案 0 :(得分:4)

试试这个:

long id;
db = helper.getWriteableDatabase();

db.beginTransaction();
Cursor c = db.rawQuery("SELECT * FROM Foo " + whereClause, whereValues);
try {
    while (cursor.moveToNext()) {
        id = cursor.getLong(cursor.getColumnIndex("_id"));
        db.delete("Foo", "_id = " + id,null);
    }
    db.setTransactionSuccessful();

}catch {
            //Error in between database transaction 
}finally {
    db.endTransaction();

}

我不确定我是否可以迭代游标并同时删除行。如果没有,您可以先将ID保存在数组中。

答案 1 :(得分:3)

不处理交易 而且,如果你这样使用它,那就完全无用 如果在整个数据操作期间没有发生错误(在try ... catch中),你应该提交(setTransactionSuccessful())。

另请注意,只有在执行多个数据操作时,交易才有用 SELECT不会操纵任何数据

所以,在所有这些题外话之后,答案是...... 是的,你可以