对android数据的操作,通常情况下,我们使用ContentProvider进行数据库的相关操作
但是,很多情况下我们需要使用多表查询或者大数据的事物处理,对SQLiteDatabase进行直接操作,可以方便的处理很多复杂的情况
我们知道在使用ContentProvider进行数据库操作时,不需要我们进行主动的关闭数据库操作
而自己创建的SQLiteDatabase实例,需要考虑好打开和关闭的时机
1. 创建一个继承自SqliteHelper的子类,一般将SqliteHelper设置为单例模式,通常我们使用Application的Context作为数据库的实例参数
2. 调用getWritableDatabase()或getReadableDatabase()可直接获取到数据库对象
3. 使用SqliteHelper获取的SQLiteDatabase对象,直接对数据库进行sql语句操作(便于多表之间的联合查询等),可方便的使用beginTransaction()等方法进行批量的事物处理,提高大数据操作的效率,查询完成后并不需要主动的关闭数据库
4.在应用的开启时进行数据库打开初始化,应用退出时进行数据库的关闭及资源释放
下面是一些描述说明,包括项目中遇到的一些问题:
问题1:在实际过程中并不能完成保证application何时退出(意外情况包括异常退出或内存不足被系统杀死)并关闭数据库
方案:
在应用开启时(通常在application中进行),先对数据库进行关闭再开启,以保障上次资源的释放
问题2:在进行应用升级操作时,由于多线程的操作,可能在安装新应用的过程中还存在工作线程进行数据的操作,如果此时(即应用退出时关闭数据库)会导致数据操作异常--releaseAndUnlock
方案:
需要对增删改查方法进行同步控制
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;
public class DBHelper {
private static DBHelper sDBHelper = null;
private SqliteHelper mSqliteHelper = null;
private DBHelper() {
}
public synchronized static DBHelper instance() {
if (sDBHelper == null) {
sDBHelper = new DBHelper();
}
return sDBHelper;
}
public synchronized void open(Context context, String dbName) {
close();
mSqliteHelper = new SqliteHelper(context, dbName, null, 1);
}
public synchronized void insert(String sql) {
if (mSqliteHelper == null) {
return;
}
mSqliteHelper.getWritableDatabase().execSQL(sql);
}
public synchronized long insert(String table, ContentValues values) {
if (mSqliteHelper == null) {
return -1;
}
return mSqliteHelper.getWritableDatabase().insert(table, null, values);
}
public synchronized int update(String table, ContentValues values,
String whereClause, String[] whereArgs) {
if (mSqliteHelper == null) {
return -1;
}
return mSqliteHelper.getWritableDatabase().update(table, values,
whereClause, whereArgs);
}
public synchronized Cursor query(String table, String[] columns,
String selection, String[] selectionArgs, String groupBy,
String having, String orderBy) {
if (mSqliteHelper == null) {
return null;
}
return mSqliteHelper.getReadableDatabase().query(table, columns,
selection, selectionArgs, groupBy, having, orderBy);
}
public synchronized Cursor query(String sql) {
if (mSqliteHelper == null) {
return null;
}
return mSqliteHelper.getReadableDatabase().rawQuery(sql, null);
}
public synchronized int delete(String table, String whereClause,
String[] whereArgs) {
if (mSqliteHelper == null) {
return -1;
}
return mSqliteHelper.getReadableDatabase().delete(table, whereClause,
whereArgs);
}
public synchronized void close() {
if (mSqliteHelper != null) {
mSqliteHelper.close();
mSqliteHelper = null;
}
}
}
异常日志:
java.lang.NullPointerException
at android.database.sqlite.SQLiteStatement.releaseAndUnlock(SQLiteStatement.java:293)
at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:99)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1900)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1839)
at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:661)
at android.database.sqlite.SQLiteDatabase.beginTransactionNonExclusive(SQLiteDatabase.java:576)
at android.database.sqlite.SQLiteStatement.acquireAndLock(SQLiteStatement.java:250)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:115)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1718)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1591
)
对android数据的操作,通常情况下,我们使用ContentProvider进行数据库的相关操作
但是,很多情况下我们需要使用多表查询或者大数据的事物处理,对SQLiteDatabase进行直接操作,可以方便的处理很多复杂的情况
我们知道在使用ContentProvider进行数据库操作时,不需要我们进行主动的关闭数据库操作
而自己创建的SQLiteDatabase实例,需要考虑好打开和关闭的时机
1. 创建一个继承自SqliteHelper的子类,一般将SqliteHelper设置为单例模式,通常我们使用Application的Context作为数据库的实例参数
2. 调用getWritableDatabase()或getReadableDatabase()可直接获取到数据库对象
3. 使用SqliteHelper获取的SQLiteDatabase对象,直接对数据库进行sql语句操作(便于多表之间的联合查询等),可方便的使用beginTransaction()等方法进行批量的事物处理,提高大数据操作的效率,查询完成后并不需要主动的关闭数据库
4.在应用的开启时进行数据库打开初始化,应用退出时进行数据库的关闭及资源释放
下面是一些描述说明,包括项目中遇到的一些问题:
问题1:在实际过程中并不能完成保证application何时退出(意外情况包括异常退出或内存不足被系统杀死)并关闭数据库
方案:
在应用开启时(通常在application中进行),先对数据库进行关闭再开启,以保障上次资源的释放
问题2:在进行应用升级操作时,由于多线程的操作,可能在安装新应用的过程中还存在工作线程进行数据的操作,如果此时(即应用退出时关闭数据库)会导致数据操作异常--releaseAndUnlock
方案:
需要对增删改查方法进行同步控制
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;
public class DBHelper {
private static DBHelper sDBHelper = null;
private SqliteHelper mSqliteHelper = null;
private DBHelper() {
}
public synchronized static DBHelper instance() {
if (sDBHelper == null) {
sDBHelper = new DBHelper();
}
return sDBHelper;
}
public synchronized void open(Context context, String dbName) {
close();
mSqliteHelper = new SqliteHelper(context, dbName, null, 1);
}
public synchronized void insert(String sql) {
if (mSqliteHelper == null) {
return;
}
mSqliteHelper.getWritableDatabase().execSQL(sql);
}
public synchronized long insert(String table, ContentValues values) {
if (mSqliteHelper == null) {
return -1;
}
return mSqliteHelper.getWritableDatabase().insert(table, null, values);
}
public synchronized int update(String table, ContentValues values,
String whereClause, String[] whereArgs) {
if (mSqliteHelper == null) {
return -1;
}
return mSqliteHelper.getWritableDatabase().update(table, values,
whereClause, whereArgs);
}
public synchronized Cursor query(String table, String[] columns,
String selection, String[] selectionArgs, String groupBy,
String having, String orderBy) {
if (mSqliteHelper == null) {
return null;
}
return mSqliteHelper.getReadableDatabase().query(table, columns,
selection, selectionArgs, groupBy, having, orderBy);
}
public synchronized Cursor query(String sql) {
if (mSqliteHelper == null) {
return null;
}
return mSqliteHelper.getReadableDatabase().rawQuery(sql, null);
}
public synchronized int delete(String table, String whereClause,
String[] whereArgs) {
if (mSqliteHelper == null) {
return -1;
}
return mSqliteHelper.getReadableDatabase().delete(table, whereClause,
whereArgs);
}
public synchronized void close() {
if (mSqliteHelper != null) {
mSqliteHelper.close();
mSqliteHelper = null;
}
}
}
异常日志:
java.lang.NullPointerException
at android.database.sqlite.SQLiteStatement.releaseAndUnlock(SQLiteStatement.java:293)
at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:99)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1900)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1839)
at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:661)
at android.database.sqlite.SQLiteDatabase.beginTransactionNonExclusive(SQLiteDatabase.java:576)
at android.database.sqlite.SQLiteStatement.acquireAndLock(SQLiteStatement.java:250)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:115)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1718)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1591
)