目录
- SQLite介绍
- 单元测试
- SQLiteOpenhelper中的方法
- SQLiteOpenhelper的构造方法参数
- 数据库的基本操作增删改查
- 封装好的增删改查方法的本质
- CursorFactory
- getDatabaseLocked源码
官网下载 http://www.sqlite.org/download.html
SQlLite 基础命令
.dump 命令 导入导出 数据库
首先配置好 测试单元
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
//测试用的jar
<uses-library android:name="android.test.runner"></uses-library>
</application>
// 指向测试类所在包.
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.memoryapp">
</instrumentation>
android中的sqllite操作在android.database 包下
SQLiteOpenhelper是一个抽象的class 封装了SQLite 打开
“`
1.两个构造方法 SQLiteOpenHelper
SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
DatabaseErrorHandler errorHandler)
主要做了赋值 和 版本号的判断(version)
“`
1.两个构造方法 SQLiteOpenHelper
SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
DatabaseErrorHandler errorHandler)
主要做了赋值 和 版本号的判断(version)
2.建造数据库 onCreate(SQLiteDatabase)
3.打开数据库 onOpen(SQLiteDatabase)
4.关闭连接 close()
5.onUpgrade(SQLiteDatabase)
6.onDowngrade(SQLiteDatabase)
7.onConfigure(SQLiteDatabase)
8.getWritableDatabase()
9.getReadableDatabase()
在SQLiteOpenHelper中主要实现getReadableDatabase和
getWritableDatabase调用的私有 getDatabaseLocked(boolean writeable) 实现了同步锁定
10.setWriteAheadLoggingEnabled(boolean)
11.getDatabaseName()
“`
SQLiteOpenHelper构造函数参数
“`
参数
name 数据库名
Context 寻找数据库路径 打开或创建数据库
version 版本号
“`
参数
name 数据库名
Context 寻找数据库路径 打开或创建数据库
version 版本号
第一次创建数据库时调用onCreate
版本号大于时 调用onUpgrade
“`
创建和打开数据库时都会调用getDatabaseLocked方法
该方法中实现了创建打开数据库 使用SQLiteDatabase.openDatabase
打开数据库 如果失败调用 mContext.openOrCreateDatabase 创建打开数据库
SQLiteDatabase 类 数据库的基本操作增删改查
execSQL(sql) // 执行sql 语句
1. public long insert(String table, String nullColumnHack, ContentValues values)
该方法出现异常返回-1
/** long insertOrThrow(String table, String nullColumnHack, ContentValues values)
与insert 相比差别是没有捕获异常**/
2.public Cursor query(boolean distinct, String table, String[] columns,
String selection, String[] selectionArgs, String groupBy,
String having, String orderBy, String limit)
public Cursor rawQuery(String sql, String[] selectionArgs)
该方法没有对sql语句处理需要自己写sql语句
3. delete(String table, String whereClause, String[] whereArgs)
构造删除sql语句
SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table +
(!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
4. public int update(String table, ContentValues values, String whereClause, String[] whereArgs)
5. deleteDatabase(File)
封装好的增删改查方法的本质(最终生成sql语句的方法)
insert 方法调用
public long insertWithOnConflict(String table, String nullColumnHack,
ContentValues initialValues, int conflictAlgorithm)
该方法处理传入参数生成sql语句,参数主要来自insert(table,null.values)传入
参数:
1.nullColumnHack may be null , SQL doesn't allow inserting a completely empty row without
naming at least one column name. If your provided <code>initialValues</code> is
empty, no column names are known and an empty row can't be inserted.
If not set to null, the <code>nullColumnHack</code> parameter
provides the name of nullable column name to explicitly insert a NULL into
in the case where your <code>initialValues</code> is empty.
2.conflictAlgorithm for insert conflict resolver
query 方法调用 (多一个CursorFactory 和 CancellationSignal )
public Cursor queryWithFactory(CursorFactory cursorFactory,
boolean distinct, String table, String[] columns,
String selection, String[] selectionArgs, String groupBy,
String having, String orderBy, String limit, CancellationSignal cancellationSignal)
query 方法出入的参数 queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
groupBy, having, orderBy, limit, null);
SQLiteQueryBuilder.buildQueryString 构造查询sql语句
3. public int updateWithOnConflict(String table, ContentValues values,
String whereClause, String[] whereArgs, int conflictAlgorithm)
构造更新sql语句
CursorFactory 是一个SQLDatabase 的内部接口
“`
public interface CursorFactory {
“`
public interface CursorFactory {
public Cursor newCursor(SQLiteDatabase db,
SQLiteCursorDriver masterQuery, String editTable,
SQLiteQuery query);
}
public interface CustomFunction {
public void callback(String[] args);
}
“`
getDatabaseLocked 源码
private SQLiteDatabase getDatabaseLocked(boolean writable) {
if (mDatabase != null) {
if (!mDatabase.isOpen()) {
// Darn! The user closed the database by calling mDatabase.close().
mDatabase = null;
} else if (!writable || !mDatabase.isReadOnly()) {
// The database is already open for business.
return mDatabase;
}
}
if (mIsInitializing) {
throw new IllegalStateException("getDatabase called recursively");
}
SQLiteDatabase db = mDatabase;
try {
mIsInitializing = true;
if (db != null) {
if (writable && db.isReadOnly()) {
db.reopenReadWrite();
}
} else if (mName == null) {
db = SQLiteDatabase.create(null);
} else {
try {
if (DEBUG_STRICT_READONLY && !writable) {
final String path = mContext.getDatabasePath(mName).getPath();
db = SQLiteDatabase.openDatabase(path, mFactory,
SQLiteDatabase.OPEN_READONLY, mErrorHandler);
} else {
db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
mFactory, mErrorHandler);
}
} catch (SQLiteException ex) {
if (writable) {
throw ex;
}
Log.e(TAG, "Couldn't open " + mName
+ " for writing (will try read-only):", ex);
final String path = mContext.getDatabasePath(mName).getPath();
db = SQLiteDatabase.openDatabase(path, mFactory,
SQLiteDatabase.OPEN_READONLY, mErrorHandler);
}
}
onConfigure(db);
final int version = db.getVersion();
if (version != mNewVersion) {
if (db.isReadOnly()) {
throw new SQLiteException("Can't upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + mName);
}
db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
if (version > mNewVersion) {
onDowngrade(db, version, mNewVersion);
} else {
onUpgrade(db, version, mNewVersion);
}
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
onOpen(db);
if (db.isReadOnly()) {
Log.w(TAG, "Opened " + mName + " in read-only mode");
}
mDatabase = db;
return db;
} finally {
mIsInitializing = false;
if (db != null && db != mDatabase) {
db.close();
}
}
}