我有一个 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/