我已经使Singelton对象向SQLiteOpenHelper
发出查询,其中我保存了getWriteableDatabase()
的实例。在整个应用程序生命周期中,对于所有select
和insert/update
个查询,我正在使用来自多个IntentService
的该实例。我已经阅读了预写日志记录(WAL),它支持并发执行查询。我使用上面的实例禁用WAL。实际上在某个时刻数据库没有返回数据,我想知道SQLite
文件是否可以被破坏,因为我使用getWritableabledatabse
来从多个意图服务进行读/写。
这种方法会发生僵局吗?
根据我的发现,如果您从多个线程访问数据库,则应启用WAL。
DatabaseAdapter.java
public class DatabaseAdapter {
private Context mContext;
private SQLiteDatabase mSqLiteDatabase;
private DatabaseHelper mDbHelper;
private static DatabaseAdapter adapter;
public static DatabaseAdapter getInstance() {
if(adapter == null) {
synchronized (DatabaseAdapter.class) {
if(adapter == null)
adapter = new DatabaseAdapter(MyApp.getInstance());
}
}
return adapter;
}
public DatabaseHelper getDatabaseHelper() {
return mDbHelper;
}
private DatabaseAdapter(Context c) {
mContext = c;
mDbHelper = new DatabaseHelper(mContext);
mSqLiteDatabase = mDbHelper.getWritableDatabase();
}
private long insert(String tableName, ContentValues contentValues) throws Exception {
this.open();
long id = mSqLiteDatabase.insert(tableName, null, contentValues);
this.close();
return id;
}
private int update(String tableName, ContentValues contentValues, int pk_id) throws Exception {
this.open();
String whereClause = mDbHelper.pk_id + " = " + pk_id;
int n = mSqLiteDatabase.update(tableName, contentValues, whereClause, null);
this.close();
return n;
}
private ArrayList<MyObject> selectChallans(String whereClause, String orderby) throws Exception {
try {
ArrayList<MyObject> arrayListObjects = new ArrayList<MyObject>();
Cursor queryCursor = mSqLiteDatabase.query(tableName, null, whereClause, null, null, null, orderby, null);
if (queryCursor == null) {
return null;
}
while (queryCursor.moveToNext()) {
MyObject myobject = getMyObject(queryCursor);
if(myobject != null)
arrayListObjects.add(myobject);
}
queryCursor.close();
return arrayListObjects;
} catch (Exception e) {
e.printStackTrace();
this.forceClose();
throw e;
}
}
}
我通过应用程序使用此Adapter单例实例进行插入/更新和选择查询。我担心mSqLiteDatabase
实例。这些函数是从多个IntentService
调用的。
答案 0 :(得分:1)
AFAIK,最佳做法是仅使用一个getWritableabledatabse
致电SQLiteOpenHelper
一次。之后,您可以将返回的database
用于所有线程,而不会出现任何问题。您必须确保使用一个数据库连接。您可以查看Good Answer以获取更多详细信息。
SqliteOpenHelper对象保留一个数据库连接。它似乎为您提供读写连接,但它确实没有。调用只读,无论如何都将获得写数据库连接。
所以,一个帮助器实例,一个数据库连接。即使您从多个线程使用它,一次一个连接。 SqliteDatabase对象使用java锁来保持序列化访问。因此,如果100个线程有一个数据库实例,则对实际磁盘数据库的调用将被序列化。
所以,一个帮助器,一个db连接,在java代码中序列化。一个线程,1000个线程,如果您使用它们之间共享的一个帮助程序实例,则所有数据库访问代码都是串行的。生活是美好的(ish)。
对我来说,我通常在SQLiteOpenHelper
课程中创建并打开Application
,然后我可以在我的应用程序的任何线程中随处使用它。