/**
* query all persons, return cursor * @return */
public Cursor queryTheCursor() {
Cursor
Cursor c = db.rawQuery(\ return c; }
我们在DBManager构造方法中实例化DBHelper并获取一个SQLiteDatabase对象,作为整个应用的数据库实例;在添加多个Person信息时,我们采用了事务处理,确保数据完整性;最后我们提供了一个closeDB方法,释放数据库资源,这一个步骤在我们整个应用关闭时执行,这个环节容易被忘记,所以朋友们要注意。
我们获取数据库实例时使用了getWritableDatabase()方法,也许朋友们会有疑问,在getWritableDatabase()和getReadableDatabase()中,你为什么选择前者作为整个应用的数据库实例呢?在这里我想和大家着重分析一下这一点。
我们来看一下SQLiteOpenHelper中的getReadableDatabase()方法:
[java]view plaincopyprint?
} /**
* close database */
public void closeDB() { }
db.close();
1. public synchronized SQLiteDatabase getReadableDatabase() { 2. if (mDatabase != null && mDatabase.isOpen()) { 3. // 如果发现mDatabase不为空并且已经打开则直接返回 4. return mDatabase; 5. } 6.
7. if (mIsInitializing) { 8. // 如果正在初始化则抛出异常
9. throw new IllegalStateException(\
cursively\
10. } 11.
12. // 开始实例化数据库mDatabase 13.
14. try {
15. // 注意这里是调用了getWritableDatabase()方法 16. return getWritableDatabase(); 17. } catch (SQLiteException e) { 18. if (mName == null)
19. throw e; // Can't open a temp database read-only! 20. Log.e(TAG, \
read-only):\21. } 22.
23. // 如果无法以可读写模式打开数据库 则以只读方式打开 24.
25. SQLiteDatabase db = null; 26. try {
27. mIsInitializing = true;
28. String path = mContext.getDatabasePath(mName).getPath();// 获
取数据库路径
29. // 以只读方式打开数据库
30. db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabas
e.OPEN_READONLY);
31. if (db.getVersion() != mNewVersion) {
32. throw new SQLiteException(\
e from version \33. + mNewVersion + \34. } 35.
36. onOpen(db);
37. Log.w(TAG, \38. mDatabase = db;// 为mDatabase指定新打开的数据库 39. return mDatabase;// 返回打开的数据库 40. } finally {
41. mIsInitializing = false;
42. if (db != null && db != mDatabase) 43. db.close(); 44. } 45. }
返回
public synchronized SQLiteDatabase getReadableDatabase() {
if (mDatabase != null && mDatabase.isOpen()) { }
if (mIsInitializing) { }
// 开始实例化数据库mDatabase try { }
// 如果无法以可读写模式打开数据库 则以只读方式打开 SQLiteDatabase db = null; try {
// 注意这里是调用了getWritableDatabase()方法 return getWritableDatabase(); if (mName == null)
throw e; // Can't open a temp database
// 如果正在初始化则抛出异常 throw new
// 如果发现mDatabase不为空并且已经打开则直接return mDatabase;
IllegalStateException(\
} catch (SQLiteException e) {
read-only!
Log.e(TAG, \
writing (will try read-only):\
path); 库
}
}
mIsInitializing = true; String path =
// 以只读方式打开数据库
db = SQLiteDatabase.openDatabase(path, mFactory, if (db.getVersion() != mNewVersion) { }
onOpen(db);
Log.w(TAG, \mDatabase = db;// 为mDatabase指定新打开的数据return mDatabase;// 返回打开的数据库 mIsInitializing = false;
if (db != null && db != mDatabase)
db.close();
throw new SQLiteException(%upgrade
+ mNewVersion + \
mContext.getDatabasePath(mName).getPath();// 获取数据库路径
SQLiteDatabase.OPEN_READONLY);
read-only database from version \
mode\
} finally {
在getReadableDatabase()方法中,首先判断是否已存在数据库实例并且是打开状态,如果是,则直接返回该实例,否则试图获取一个可读写模式的数据库实例,如果遇到磁盘空间已满等情况获取失败的话,再以只读模式打开数据库,获取数据库实例并返回,然后为mDatabase赋值为最新打开的数据库实例。既然有可能调用到getWritableDatabase()方法,我们就要看一下了:
[java]view plaincopyprint?
1. public synchronized SQLiteDatabase getWritableDatabase() {
2. if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOn
ly()) {
3. // 如果mDatabase不为空已打开并且不是只读模式 则返回该实例
4. return mDatabase; 5. } 6.
7. if (mIsInitializing) {
8. throw new IllegalStateException(\
cursively\9. } 10.
11. // If we have a read-only database open, someone could be using it
12. // (though they shouldn't), which would cause a lock to be held on
13. // the file, and our attempts to open the database read-write woul
d
14. // fail waiting for the file lock. To prevent that, we acquire the
15. // lock on the read-only database, which shuts out other users. 16.
17. boolean success = false; 18. SQLiteDatabase db = null;
19. // 如果mDatabase不为空则加锁 阻止其他的操作 20. if (mDatabase != null) 21. mDatabase.lock(); 22. try {
23. mIsInitializing = true; 24. if (mName == null) {
25. db = SQLiteDatabase.create(null); 26. } else {
27. // 打开或创建数据库
28. db = mContext.openOrCreateDatabase(mName, 0, mFactory); 29. }
30. // 获取数据库版本(如果刚创建的数据库,版本为0) 31. int version = db.getVersion();
32. // 比较版本(我们代码中的版本mNewVersion为1) 33. if (version != mNewVersion) {