Android开发学习教程(31)- Android SQLite使用教程
—— 不为跑赢世界,只为超越自己。
Android提供了四种不同的方式用于本地存储数据,上一篇我们讲了文件存储和SharedPreferences存储,现在我们来看 SQLite 存储。SQLite 是一个结构查询基础数据库,我们可以说它是一个关系数据库。Android 系统有内部已经实现了CRUD(创建、读取、更新、删除)操作,在 Android 的 android.database 和 android.database.sqlite 包中提供了一组可用的类。
在使用 SQLite 时,可能有两种不同的方式来执行不同的操作如创建、读取、更新和删除。一种是编写原始SQL语句,另一种是使用参数化函数,或者我们可以说是参数化查询。
创建数据库
使用 SQLiteOpenHelper 类在 Android 中创建数据库非常简单。SQLiteOpenHelper 是一个抽象类,具有两个抽象方法 onCreate(SQLiteDatabase db) 和 onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 以及更多对数据库有用的函数。每当我们需要创建数据库时,我们必须扩展 SQLiteOpenHelper 类,如下所示:
public class SqliteManager extends SQLiteOpenHelper { public static final String DATABASE_NAME = "test.db"; public static final int version = 1; public SqliteManager(Context context) { super(context, DATABASE_NAME, null, version); } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { String dbQuery = "CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT, description TEXT)"; sqLiteDatabase.execSQL(dbQuery); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) { } }
onCreate(SQLiteDatabase sqLiteDatabase)方法在整个应用程序生命周期中只调用一次,每当第一次调用 SQLiteOpenHelper 类中的 getReadableDatabase() 或 getWritableDatabase() 函数时都会调用它,因此 SQLiteOpenHelper 类在创建后调用 onCreate() 方法数据库并实例化 SQLiteDatabase 对象。数据库名称在构造函数调用中传递。
onUpgrade(SQLiteDatabase db,int oldVersion, int newVersion)仅在升级APP版本并且数据库有更新时调用,因此需要更新版本时我们必须增加version的值,比如app从1.0.0升级到1.0.1的时候数据库需要升级的话,对应的version就要改成大于1的任何整数即可。在 onUpgrade 方法中,我们可以编写SQL语句来执行所需的任何操作。如增加一张新表,增加一条数据记录等等。
在 Sqlite 中插入、读取、删除和更新操作
执行插入、读取、删除、更新操作有两种不同的方式:
1. 编写参数化查询(推荐)
2. 编写原始SQL语句
参数化查询:这些查询使用SDK内置的函数来插入、读取、删除或更新数据。这些操作相关的函数在 SQLiteDatabase 类中提供。
原始SQL语句:这些是类似于 MySql、Sql Server 等其他数据库的 sql 查询语句,将这些SQL语句当做参数传给 rawQuery(String sql,String [] selectionArgs) 或 execSQL(String sql,Object [] bindArgs) 方法来执行操作。
注: Android 官方不建议使用原始SQL语句来执行插入、读取、更新、删除操作,建议始终使用 SQLiteDatabase 类的内置函数执行插入、查询、更新、删除操作。原因如下:
当使用原始SQL语句执行插入操作的时:
public void insertItem(Item item) { String query = "INSERT INTO " + ItemTable.NAME + " VALUES (0,?,?)"; SQLiteDatabase db = getWritableDatabase(); db.execSQL(query, new String[]{item.name, item.description}); db.close(); }
在使用原始查询时,我们永远不会知道操作的结果,即db.execSQL的返回值是void类型。而使用参数化查询函数则会返回一个值来表示操作成功或失败。所以建议使用参数化查询。
插入操作
使用参数化查询执行插入操作,我们必须调用 SQLiteDatabase 类中内置的插入函数:
public long insert(String tableName,String nullColumnHack,ContentValues values)
insert()函数具有三个参数,tableName 是要插入数据表的名称。nullColumnHack可能为空,SQL不允许在插入一个完全空的行时不指定至少一个列名。如果提供的值为空,则不知道列名,并且无法插入空行。如果未设置为null,则nullColumnHack参数提供可为null的列名的名称,以便在值为空的情况下显式插入null。values是包含一行数据的键值对。键应该是列名值是列值。如果插入成功,insert 函数将返回一个 long 值,即插入的行数,否则返回 - 1。
举个栗子:
public void addItem(Item item) { SQLiteDatabase db = getWritableDatabase(); ContentValues contentValues = new ContentValues(); contentValues.put("name", item.name); contentValues.put("description", item.description); db.insert("Items", null, contentValues); db.close(); }
更新操作
更新操作与插入操作非常相似,但它需要两个额外的参数,它不需要 nullColumnHack。它共有四个参数,其中两个类似于插入函数,即 tableName 和 contentValues。另外两个是 whereClause(String) 和 whereArgs(String[]):
public int update(String tableName,ContentValues contentValues,String whereClause,String[] whereArgs)
这里 whereClause 是告诉数据库在哪里更新表中的数据,建议在 whereClause 字符串中使用占位符 ? 表示将要传递的值。类似地,whereArgs 数组将包含那些传递给对应的占位符 ? 的值。如果成功,更新函数将返回受影响的行数,否则返回 0。
举个栗子:
public void updateItem(Item item) { SQLiteDatabase db = getWritableDatabase(); ContentValues contentValues = new ContentValues(); contentValues.put("id", item.id); contentValues.put("name", item.name); contentValues.put("description", item.description); String whereClause = "id=?"; String whereArgs[] = {item.id.toString()}; db.update("Items", contentValues, whereClause, whereArgs); }
删除操作
与插入和更新类似,SQLiteDatabase 类中提供了删除功能,因此删除与更新功能非常相似,除了 ContentValues 对象,因为它在删除中不需要。delete 函数有三个参数,它们与更新函数的参数完全相似,使用方式与更新函数相同。
举个栗子:
public void deleteItem(Item item) { SQLiteDatabase db = getWritableDatabase(); String whereClause = "id=?"; String whereArgs[] = {item.id.toString()}; db.delete("Items", whereClause, whereArgs); }
这里 whereClause 是可选的,传递 null 将删除表中的所有行。如果 whereClause 传递,删除函数将返回受影响的行数,否则将返回 0。
注:如果要删除所有行并要求返回删除行的计数,则将 1 作为 whereClause 传递。
查询操作
从数据库表中读取与插入、更新和删除等其他函数有点不同。SQLiteDatabase 类提供query()方法来从表中读取数据。query() 方法被不同的参数集重载。它返回Cursor对象,因此 Cursor 是一个带有查询数据的结果集,它提供了不同的功能,在读取数据时非常有用。
以下是一些重载的查询函数:
public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
public Cursor query (boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
查询重载函数中的大多数参数都是可选的,除了 table 和不同的任何其他参数都可以作为 null 传递。如果 distinct 作为 true 传递,则游标数据集将没有任何重复行。
public ArrayList- readAllItems() { ArrayList
- items = new ArrayList<>(); SQLiteDatabase db = getReadableDatabase(); //see above point 2 function Cursor cursor = db.query("Items" , null// columns - null will give all , null// selection , null// selection arguments , null// groupBy , null// having , null// no need or order by for now; if (cursor != null) { while (cursor.moveToNext()) { // move the cursor to next row if there is any to read it's data Item item = readItem(cursor); items.add(item); } } return items; } private Item readItem(Cursor cursor) { Item item = new Item(); item.id = cursor.getInt(cursor.getColumnIndex(ItemTable.COL_ID)); item.name = cursor.getString(cursor.getColumnIndex(ItemTable.COL_NAME)); item.description = cursor.getString(cursor.getColumnIndex(ItemTable.COL_DESCRIPTION)); return item; }
本篇源码下载地址:https://pan.baidu.com/s/1Bq_LziAfSvf4wlLq8u9Ctg 提取码: helu
------转载请注明出处,感谢您对原创作者的支持------
有偿提供技术支持、Bug修复、项目外包、毕业设计、大小作业
Android学习小站
Q Q:1095817610
微信:jx-helu
邮箱:1095817610@qq.com
添加请备注"Android学习小站"
