资讯专栏INFORMATION COLUMN

Database (数据库)

tinylcy / 3125人阅读

摘要:和用来向表中插入新的行数据,每个对象都将一个行记录对应。数据库查询结果作为对象返回。会缓存数据库实例。如果数据库不存在,就会执行方法,如果数据库版本发生变化则会执行方法。文件通常是不存在数据库中的,应该存放文件的路径地址。

  

SQLite 数据库文件存储在设备上的 /data/data/package_name/databases 文件夹中,所有的数据库都市私有的,只能被创建者访问。
使用数据库时最好的做法是将底层数据库封装起来,只公开与该数据库进行交互时必须使用的公有方法和常量,这一般会用到所谓的辅助类。

ContentValue 和 Cursor

Content Value 用来向表中插入新的行数据,每个 ContentValues 对象都将一个行记录对应。
数据库查询结果作为 Cursor 对象返回。Cursor 是底层数据中的结果集的指针,它没有提取和返回结果值的副本。
Cursor 常用的几个方法:

moveToFirst

moveToNext

moveToPrevious

moveToPosition

getCount

getColumnIndexOrThrow

getColumnName

getColumnNames

getPosition

Android 提供了一种方便的机制,可以确保异步执行查询,API Level 11 引入了 CursorLoader 类和相关的 Loader Manager,现在他们已经成为了支持库的一部分,从而允许你在支持早期的 Android 版本的同时使用这些功能。


SQLiteOpenHelper

是一个抽象类,用来实现创建、打开和升级数据库。会缓存数据库实例。通过 onCreate 和 onUpgrade 方法来分别处理创建新数据库和升级新版本数据库。

等到需要数据库时在创建和打开这些数据库是一种很好的做法,SQLiteOpenHelper 会再打开数据库后缓存他的实例,一般情况下无需手动关闭数据库。

  

数据库操作(特别是打开或创建数据库)需要很长时间才能完成,为了确保不影响用户操作体验,应该使所有数据库事物异步执行。

通常可以使用 SQLiteOpenHelper 的 getWritableDatabase 或者 getReadableDatabase 来分别打开一个可写或只读的实例。如果数据库不存在,就会执行 onCreate 方法,如果数据库版本发生变化则会执行 onUpgrade 方法。

也可以不使用 SQLiteOpenHelper 打开数据库实例,可以通过 Context 对象的 openOrCreateDatabase 方法

public class HoardDBOPenHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "myDatabase.db";
    private static final String DATABASE_TABLE = "GoldHoards";
    private static final int DATABASE_VERSION = 1;

    public static final String KEY_ID = "_id";

    public static final String KEY_GOLD_HOARD_NAME_COLUMN = "GOLD_HOARD_NAME_COLUMN";
    public static final String KEY_GOLD_HOARD_ACCESSIBLE_COLUMN = "OLD_HOARD_ACCESSIBLE_COLUMN";
    public static final String KEY_GOLD_HOARDED_COLUMN = "GOLD_HOARDED_COLUMN";

    private static final String DATABASE_CREATE = "create table "
        + DATABASE_NAME + "(" + KEY_ID
        + "integer primary key autoincrement, "
        + KEY_GOLD_HOARD_NAME_COLUMN + " text not null, "
        + KEY_GOLD_HOARDED_COLUMN + " float, "
        + KEY_GOLD_HOARD_ACCESSIBLE_COLUMN + " integer);";

    public HoardDBOPenHelper(Context context, String name,
        CursorFactory factory, int version,
        DatabaseErrorHandler errorHandler) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DATABASE_CREATE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w("TaskDBAdapter", "Upgrading from version " + oldVersion + " to "
        + newVersion + ", which will destroy all old data");

        db.execSQL("DROP TABLE IF IT EXISTS " + DATABASE_CREATE);

        onCreate(db);
    }
}
  

数据库设计注意事项

每个表都增加一个 _id 作为每一行的索引字段。如果使用 Content Provider 就必须要有一个 唯一的 ID 字段。

文件通常是不存在数据库中的,应该存放文件的路径地址。


SQLiteDatabase

数据库操作实例,提供了操作数据库的一切动作,包含增删改查、执行 SQL 语句。


数据库查询

每个数据库查询都会作为一个 Cursor 返回,这就使得 Android 可以按需检索和释放行和列的值,从而更加高效的管理资源。

要对一个数据库对象进行查询,需要使用 query 方法,并传入以下的一些参数:

一个可选的布尔值,用来指定结果集是否只包含唯一的值。

要查询的表的名称。

一个字符串数组形式的投影,列出了包含在结果集中的列。

一条 where 子句,定义了要返回的行。可以在其中包含“?” 通配符,它将会被通过选择参数传入的值替换。

一个选择参数字符串的数组,它将会替换 where 子句中的“?”,通配符。

一条 group by 子句,用来定义返回的行的分组方式。

一条 having 子句,如果指定了一条 group by 子句,则盖子句会定义要包含那些行组。

一个字符串,用来描述返回的行的顺序。

一个字符串,用来定义结果集中的最大行数。

public void queryHoard() {
    String[] result_cloums = new String[] { KEY_ID,
        KEY_GOLD_HOARD_ACCESSIBLE_COLUMN, KEY_GOLD_HOARDED_COLUMN };

    // 指定用于限制结果的 where 子句
    String where = KEY_GOLD_HOARD_ACCESSIBLE_COLUMN + "=" + 1;

    // 根据需要把以下语句替换为有效的SQL语句
    String[] whereArgs = null;
    String groupBy = null;
    String having = null;
    String order = null;

    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.query(DATABASE_NAME, result_cloums, where,
        whereArgs, groupBy, having, order);
}


从 Cursor 中提取值

要 从 Cursor 中提取值,首先要使用前面描述过的 moveTo 系列的方法将游标放到结果 Cursor 的正确行中,然后使用类型安全的 get 方法来返回存储在指定列的当前行中的值。为了找到特定列在游标中的索引,需要使用 getColumnIndex 和 getColumnIndexOrThrow 方法。
当你认为列在所有情况下都存在时,使用 getColumnIndexOrThrow 是一种不错的办法,当列有可能不存在游标中时,使用 getColumnIndex 可以检查结果是否为 -1 比捕获异常更加高效。

int columnIndex = cursor.getColumnIndex(KEY_GOLD_HOARDED_COLUMN);
if (columnIndex > -1) {
    String columnValue = cursor.getColumnName(columnIndex);
    // 存在时
} else {
    // 不存在
}

从 Cursor 中获取值:

float totalHoard = 0f;
float averageHoard = 0f;

// 找出所用列的索引
int GOLD_HOARDED_COLUMN_INDEX = cursor.getColumnIndexOrThrow(KEY_GOLD_HOARD_NAME_COLUMN);

// 遍历游标
while (cursor.moveToNext()) {
    float hoard = cursor.getFloat(GOLD_HOARDED_COLUMN_INDEX);
    totalHoard += hoard;
}

// 计算平均值
float cursorCount = cursor.getCount();
averageHoard = cursorCount > 0 ? (totalHoard / cursorCount) : Float.NaN;

// 完成之后关闭游标
cursor.close();


添加、更新和删除

SQLiteDatabase 提供了 insert、delete、update 方法来封装执行这些操作需要的 SQL 语句。如果你希望手动去执行这些操作,需要用到 execSQL 方法可以对数据库表执行有效的 SQL 语句。

1. 插入行

// 创建一个要插入的行新值
ContentValues contentValues = new ContentValues();

// 为每行赋值
contentValues.put(KEY_GOLD_HOARD_ACCESSIBLE_COLUMN, "");
contentValues.put(KEY_GOLD_HOARD_NAME_COLUMN, 123);
contentValues.put(KEY_GOLD_HOARDED_COLUMN, true);

// 把行插入到表中
SQLiteDatabase sdb = this.getReadableDatabase();
sdb.insert(this.DATABASE_TABLE, null, contentValues);

insert 方法的第二个参数称为 null 列侵入(null column hack),如果想添加一个空行,在传入 ContentValues 还必须传入一个显示的 null。

2. 更新行

// 创建更新行的 ContentValues
ContentValues updatedValues = new ContentValues();

// 为每一行赋值
updatedValues.put(KEY_GOLD_HOARDED_COLUMN, false);

// 指定一个 where 子语句定义那些行应该被更新
String where = KEY_ID + "=" + 1;
String[] whereArgs = null;

// 使用新值更新数据库记录
SQLiteDatabase sdb = getReadableDatabase();
sdb.update(DATABASE_TABLE, updatedValues, where, whereArgs);

3. 删除行

// 指定一个 where 子语句定义那些行应该被删除
String where = KEY_ID + "=" + 1;
String[] whereArgs = null;

// 使用新值更新数据库记录
SQLiteDatabase sdb = getReadableDatabase();
sdb.delete(DATABASE_TABLE, where, whereArgs);

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/12075.html

相关文章

  • [转]:tbox中据库的使用

    摘要:目前支持两种关系型数据库需要链接对应的和,并对其接口进行了封装,使用更加的方便简洁并且只需要换个,就可以随时切换成其他数据库引擎,而不需要修改接口。 TBOX目前支持sqlite3、mysql两种关系型数据库(需要链接对应的libsqlite3.a和libmysql.a),并对其接口进行了封装,使用更加的方便简洁并且只需要换个url,就可以随时切换成其他数据库引擎,而不需要修改接口。 ...

    yacheng 评论0 收藏0
  • [转]:tbox中据库的使用

    摘要:目前支持两种关系型数据库需要链接对应的和,并对其接口进行了封装,使用更加的方便简洁并且只需要换个,就可以随时切换成其他数据库引擎,而不需要修改接口。 TBOX目前支持sqlite3、mysql两种关系型数据库(需要链接对应的libsqlite3.a和libmysql.a),并对其接口进行了封装,使用更加的方便简洁并且只需要换个url,就可以随时切换成其他数据库引擎,而不需要修改接口。 ...

    Scliang 评论0 收藏0
  • [转]:tbox中据库的使用

    摘要:目前支持两种关系型数据库需要链接对应的和,并对其接口进行了封装,使用更加的方便简洁并且只需要换个,就可以随时切换成其他数据库引擎,而不需要修改接口。 TBOX目前支持sqlite3、mysql两种关系型数据库(需要链接对应的libsqlite3.a和libmysql.a),并对其接口进行了封装,使用更加的方便简洁并且只需要换个url,就可以随时切换成其他数据库引擎,而不需要修改接口。 ...

    _ang 评论0 收藏0
  • [转]:tbox中据库的使用

    摘要:目前支持两种关系型数据库需要链接对应的和,并对其接口进行了封装,使用更加的方便简洁并且只需要换个,就可以随时切换成其他数据库引擎,而不需要修改接口。 TBOX目前支持sqlite3、mysql两种关系型数据库(需要链接对应的libsqlite3.a和libmysql.a),并对其接口进行了封装,使用更加的方便简洁并且只需要换个url,就可以随时切换成其他数据库引擎,而不需要修改接口。 ...

    raise_yang 评论0 收藏0
  • [转]:tbox中据库的使用

    摘要:目前支持两种关系型数据库需要链接对应的和,并对其接口进行了封装,使用更加的方便简洁并且只需要换个,就可以随时切换成其他数据库引擎,而不需要修改接口。 TBOX目前支持sqlite3、mysql两种关系型数据库(需要链接对应的libsqlite3.a和libmysql.a),并对其接口进行了封装,使用更加的方便简洁并且只需要换个url,就可以随时切换成其他数据库引擎,而不需要修改接口。 ...

    animabear 评论0 收藏0
  • 何成为 QueryPHP 开发者

    摘要:文档开发基于单元测试实现的自动化文档当前文档开发计划功能开发当前计划功能技术债务清偿当前技术债务单元测试尽可能减少当前单元测试成为开发者需要加入我们的组织,如有相关意愿请发送邮件至小牛哥,我们会联系你的。 QueryPHP 非常欢迎各位给我们共同的伟大的作品添砖加瓦,实现为 PHP 社区提供一个好框架的美好愿景。 文档开发.基于单元测试实现的自动化文档 当前文档开发 计划功能.开发...

    bigdevil_s 评论0 收藏0

发表评论

0条评论

tinylcy

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<