1、定义模式和合约类
SQLite数据库中一个比较主要的概念就是Schema(模式):对数据库如何进行组织的一种形式化定义。模式就反映在我们用来创建数据库的SQL语句上。
同样地,创建一个辅助类,也就是合约类,它以一种系统的、自我描述的方式显式地指定了这个模式的布局。合约类包含了URI,表,列的名字的常量。我们需要在合约类的顶层里存放我们数据库的全局定义,然后在这个类里面创建一个个内部类,来描述每个表的内容。
(注意:通过实现BaseColumns接口,我们的内部类就能继承一个称之为_ID的主键)
下面举例说明:
public static abstract class FeedEntry implements BaseColumns { public static final String TABLE_NAME = "entry"; public static final String COLUMN_NAME_ENTRY_ID = "entryid"; public static final String COLUMN_NAME_TITLE = "title"; public static final String COLUMN_NAME_SUBTITLE = "subtitle"; ... }
为了避免实例化这个合约类,我们需要这样定义构造函数:
private FeedReaderContract() {}
2、使用SQL Helper创建数据库
当定义好数据库之后,我们应该实现创建和管理数据库和表的方法。下面是创建和删除表的典型语句:
private static final String TEXT_TYPE = " TEXT"; private static final String COMMA_SEP = ","; private static final String SQL_CREATE_ENTRIES = "CREATE TABLE " + FeedReaderContract.FeedEntry.TABLE_NAME + " (" + FeedReaderContract.FeedEntry._ID + " INTEGER PRIMARY KEY," + FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP + FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP + ... // Any other options for the CREATE command " )"; private static final String SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS " + TABLE_NAME_ENTRIES;
就像保存在内部存储器里的文件一样,Android将我们创建的数据库保存在它对应的应用程序私有空间里,这样就保证了我们的数据是安全的,不会为其他应用程序利用。
当我们通过SQLiteOpenHelper这个类取得数据库的引用时,系统在需要而且不是应用启动期间,可能会执行长时间的创建和更新数据库的操作。所有对数据库的操作都是通过调用getWritableDatabase()或getReadableDatabase()来做的。(注意:由于上述操作有可能是耗时的,所以确保是在后台线程里调用getWritableDatabase()或getReadableDatabase()。)
为了使用SQLiteOpenHelper,我们需要创建一个它的子类,并实现onCreate(),onUpgrade()和onOpen()等回调方法,有需要的话还可以实现onDowngrade()方法。下面举例说明:public class FeedReaderDbHelper extends SQLiteOpenHelper { // 如果改变了数据库的模式,就需要增加数据库的版本号. public static final int DATABASE_VERSION = 1; public static final String DATABASE_NAME = "FeedReader.db"; public FeedReaderDbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } public void onCreate(SQLiteDatabase db) { db.execSQL(SQL_CREATE_ENTRIES); } public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 这个数据库仅仅是在线数据的缓存,因此它的更新策略就是简单地丢弃旧数据并重新开始 db.execSQL(SQL_DELETE_ENTRIES); onCreate(db); } public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { onUpgrade(db, oldVersion, newVersion); } }
然后,就可以通过下面的语句来实例化我们自己的SQLiteOpenHelper了:FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext());
3、往数据库添加数据
我们是通过给insert()方法传递一个ContentValues对象来往数据库中插入数据的:// 以写方式取得数据库 SQLiteDatabase db = mDbHelper.getWritableDatabase(); // 创建一组values的map,其中列名作为key ContentValues values = new ContentValues(); values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID, id); values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE, title); values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_CONTENT, content); // 插入新的一行,然后返回这行的主键 long newRowId; newRowId = db.insert( FeedReaderContract.FeedEntry.TABLE_NAME, FeedReaderContract.FeedEntry.COLUMN_NAME_NULLABLE, values);
insert()方法的第一个参数是表名,第二个参数则提供了当ContentValues为空时也能插入新行的那些允许插入NULL值的列(如果这个参数设为null,当没有给那些允许为空的列提供值的时候,则不会插入新行)。
4、从数据库读取信息
我们可以通过给query()方法传递选择条件和查询列来从数据库读取数据。这个方法结合了insert()和update()方法中的参数,只是这个选择列的列表定义的是我们想要获取的数据,而不是要插入的数据。查询结果返回一个Cursor对象。SQLiteDatabase db = mDbHelper.getReadableDatabase(); // 指定了要查询的列 String[] projection = { FeedReaderContract.FeedEntry._ID, FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE, FeedReaderContract.FeedEntry.COLUMN_NAME_UPDATED, ... }; // 查询结果的排序方式 String sortOrder = FeedReaderContract.FeedEntry.COLUMN_NAME_UPDATED + " DESC"; Cursor c = db.query( FeedReaderContract.FeedEntry.TABLE_NAME, // 查询的表 projection, // 要返回的列 selection, // 查询条件 selectionArgs, // 查询条件的参数 null, // 列的分组 null, // 过滤列的分组 sortOrder // 排序方式 );
为了查看查询结果中的行,我们必须在读取数据之前使用Cursor的移动方法。通常来说,我们使用moveToFirst()方法来把初始读取位置定位到第一行。对于Cursor中的每一行数据,我们可以使用Cursor的获取方法来读取列的值,比如getString()或getLong()这样的方法,对于这样的每一个读取方法,要指定你想获取的列索引。比如:cursor.moveToFirst(); long itemId = cursor.getLong( cursor.getColumnIndexOrThrow(FeedReaderContract.FeedEntry._ID) );
5、从数据库中删除数据
为了从表中删除数据,我们需要提供选择条件。数据库的API提供了一种能够防止SQL注入的创建查询条件的机制,这种机制即是将选择语句和选择参数分离。比如:// 定义查询条件 String selection = FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?"; // 指定查询参数 String[] selectionArgs = { String.valueOf(rowId) }; // 处理查询 db.delete(table_name, selection, selectionArgs);
6、更新数据库
使用update()方法来更新数据库中的数据,实际上是insert()和delete()的结合。例如:SQLiteDatabase db = mDbHelper.getReadableDatabase(); // 定义列的新值 ContentValues values = new ContentValues(); values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE, title); // 基于ID来确定哪行被更新 String selection = FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?"; String[] selectionArgs = { String.valueOf(rowId) }; int count = db.update( FeedReaderDbHelper.FeedEntry.TABLE_NAME, values, selection, selectionArgs);