如何对SQLiteOpenHelper进行多次调用作为单个原子事务?

时间:2012-12-24 13:30:07

标签: java android multithreading sqlite concurrency

我有一个实现单例模式的SQLiteOpenHelper类,有三种方法:addLogs()getLogs()deleteLogs()。七个线程(在某些时间表由BroadcastReceiver触发)访问数据库 - 其中六个仅使用addLogs(),另一个使用getLogs()并在其之前调用deleteLogs()饰面。

我的问题是,因为最后一个线程对SQLite数据库进行两次不同的调用,所以其他线程甚至可以在调用addLogs()之前调用deleteLogs(),这会破坏我的输出。如何让一个线程将对SQLiteOpenHelper的两次调用视为单个原子事务?

我尝试了什么:在ReentrantLock中创建一个静态SQLiteOpenHelper成员,并在他们之前和之后的七个主题中的每个主题中调用lock()unlock()交易。其他六个线程仍然通过,即使最后一个仍然具有锁定,它在getLogs()之前调用并在deleteLogs()之后释放。

UPDATE:这是访问这两种方法的第七个线程。

public class Uploader extends Thread {

    private Context context;

    public Uploader(Context context) {
        this.context = context;
    }

    @Override
    public void run() {
        Logger.d("STARTED: Uploader");
        DB db = DB.getInstance(context);
        List<JsonLog> logs = db.getLogs(); // FIRST CALL
        String json = new Gson().toJson(logs); // convert to JSON

        // connect to the server and upload
        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(This.URL);
        post.setHeader("content-type", "application/json");
        try {
            Logger.d("to upload: " + json);
            StringEntity se = new StringEntity(json);
            post.setEntity(se);
            StatusLine status = client.execute(post).getStatusLine();
            // if upload is successful
            if (status.getStatusCode() == HttpStatus.SC_OK) {
                db.deleteLogs(); // SECOND CALL
            } else {
                Logger.d("Uploader failed. " + status.getStatusCode() + ": " + status.getReasonPhrase());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Logger.d("FINISHED: Uploader");
    }

}

1 个答案:

答案 0 :(得分:3)

SQLite的事务与db.beginTransaction()db.setTransactionSuccessful()中的事务相同,用于标记要提交的Tx,db.endTransaction()最终标记要执行的Tx。

因此,您可以在getLogs() beginTransactiondeleteLogs中将其标记为已完成(并且已成功)。

[更新] 现在使用您的代码段,您可能希望在第一次调用之前和beginTransaction块中调用finally,这会将try-catch阻止调用添加到endTransaction。在try部分结束时,如果状态正常,您可以致电setTransactionSuccessfuldelete来电之后。