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

标签 java android multithreading sqlite concurrency

我有一个 SQLiteOpenHelper 类,它实现单例模式并具有三个方法:addLogs()getLogs() >删除日志()。七个线程(由 BroadcastReceiver 按特定计划触发)访问数据库 - 其中六个仅使用 addLogs(),另一个使用 getLogs() 并在完成之前调用 deleteLogs()

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

我尝试过的方法:在SQLiteOpenHelper中创建一个静态ReentrantLock成员,并调用lock()unlock( ) 来自七个线程在其事务之前和之后的每一个。即使最后一个线程仍然拥有锁,其他六个线程仍然可以通过,它在 getLogs() 之前调用并在 deleteLogs() 之后释放。

更新:这是访问这两个方法的第七个线程。

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");
    }

}

最佳答案

SQLite 具有如 db.beginTransaction()db.setTransactionSuccessful() 中的事务来标记要提交的 Tx 和 db.endTransaction() 最终将 Tx 标记为已完成。

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

[更新] 现在,有了您的代码 fragment ,您可能希望在第一次调用之前和 finally block 中调用 beginTransaction,这会添加到 try-catch阻止调用endTransaction。在 try 部分的末尾,如果状态正常,您将调用 setTransactionSuccessful (在 delete 调用之后。

关于java - 如何将 SQLiteOpenHelper 作为单个原子事务进行多次调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14022042/

相关文章:

android - 如何将图像保存到数据库中

Android:StaggeredGridLayoutManager 在初始化时滚动到顶部

java - 我如何检测我的方法在等待什么?

C pthreads 传递局部变量

C# 线程池 - OutOfMemoryException

java - 运行 exec() 时出错。命令 : Working Directory: null Environment: null - how to execute a binary in Android correctly on a non-rooted device?

java - JFrame 中的错误

java - 在 servlet web 应用程序中找出与 MAC 地址关联的 IP 地址

java - 如何截取 lwuit 应用程序的屏幕截图,但不在模拟器中

java - 仅在 androidTest : Invoke-customs are only supported starting with Android O