数据存储之使用SQL数据库保存数据

来源:互联网 发布:东京好玩的地方 知乎 编辑:程序博客网 时间:2024/05/16 09:36

为了重复或结构化的数据而保存数据到数据库是非常理想,比如联系信息。一般来说在Android上假设你熟悉SQL数据库,那么它将帮助你开始使用SQLite数据库。API在Android上通过调用android.database.sqlite包而需要使用一个数据库是很有必要的。

1、定义一个模式和合同

SQL数据库的一个主要原则的模式:一个正式宣布数据库如何被组织。在SQL语句中,模式是反映你可以用它来创建你的数据库。你可能会发现,这有助于创建一个同伴类,称为合同类,你的模式在一个系统和自我记录的方式下显式地指定模式的布局。

对于常量来说合同类是一个容器,它们还为uri、表和列定义名称。该合同类允许你使用相同的常量跨所有其他类放在同一个包内。这可以让你在一个地方改变一个列名称,并让它通过你的代码进行传播。

组织一个合同类的较好的方式是设置定义,在根层次的类中它对于你的整个数据库来讲是全局。然后为每个表创建一个内部类并列举了其列。

例如,这个代码片段为单个表定义了表名和列名:

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";    ...}
以防止有人不小心实例化类的合同,给它一个空构造函数。

// 防止FeedReaderContract类被实例化private FeedReaderContract() {}
2、使用SQL助手创建一个数据库

无论你的数据库看起来如何一旦你已经定义了,你应该实现方法,创建和维护数据库和表。下面是一些典型的语句,创建和删除一个表:

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类中一套api是很有用的。当你用这个类为你的数据库来获取引用时,系统只在需要时执行可能长时间运行的操作创建和更新数据库,而不是在应用程序启动。所有你需要做的就是调用getWritableDatabase()或getReadableDatabase()。

注意:因为他们可以长时间运行,确保你调用getWritableDatabase()或getReadableDatabase()在一个后台线程,例如IntentService或 AsyncTask。

使用SQLiteOpenHelper,创建一个子类,覆盖了onCreate()、onUpgrade()和onOpen()回调方法。你可能也想实现onDowngrade(),但这不是必需的。

举例来说,这里的一个实现,它使用一些的SQLiteOpenHelper上面显示的命令:

public class FeedReaderDbHelper extends SQLiteOpenHelper {    // If you change the database schema, you must increment the database version.    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) {        // This database is only a cache for online data, so its upgrade policy is        // to simply to discard the data and start over        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、 将信息存入数据库

通过一个ContentValues对象的Insert()方法将数据插入到数据库:

// Gets the data repository in write modeSQLiteDatabase db = mDbHelper.getWritableDatabase();// Create a new map of values, where column names are the keysContentValues 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);// Insert the new row, returning the primary key value of the new rowlong 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();// Define a projection that specifies which columns from the database// you will actually use after this query.String[] projection = {    FeedReaderContract.FeedEntry._ID,    FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE,    FeedReaderContract.FeedEntry.COLUMN_NAME_UPDATED,    ...    };// How you want the results sorted in the resulting CursorString sortOrder =    FeedReaderContract.FeedEntry.COLUMN_NAME_UPDATED + " DESC";Cursor c = db.query(    FeedReaderContract.FeedEntry.TABLE_NAME,  // The table to query    projection,                               // The columns to return    selection,                                // The columns for the WHERE clause    selectionArgs,                            // The values for the WHERE clause    null,                                     // don't group the rows    null,                                     // don't filter by row groups    sortOrder                                 // The sort order    );
在你开始阅读值之前,你必须调用Cursor的其中一个移动方法,看中一行光标。一般来说,你应该以调用moveToFirst()方法开始,它将“read position”作为第一个入口进入结果。对于每一行, 你都可以调用Cursor的其中一个获取方法来读取列的值,如getString()或getLong()。对于每个get方法,你必须通过你所期望的索引位置的列,你可以通过调用getColumnIndex()或getColumnIndexOrThrow()来获取。例如:

cursor.moveToFirst();long itemId = cursor.getLong(    cursor.getColumnIndexOrThrow(FeedReaderContract.FeedEntry._ID));
5、 从数据库中删除信息

从一个表中删除行时,你需要提供选择标准,确定行。数据库API提供了一种机制来创建选择标准,防止SQL注入。将选择规范机制划分成选择条款和选择参数。从这个子句定义的列看,它依然允许你合并列测试。这个参数作为再一次测试的值绑定到条款。因为结果的方式处理不同与一个常规的SQL语句,它是免疫SQL注入。

// Define 'where' part of query.String selection = FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";// Specify arguments in placeholder order.String[] selelectionArgs = { String.valueOf(rowId) };// Issue SQL statement.db.delete(table_name, mySelection, selectionArgs);
6、 更新数据库

当你需要修改你的数据库值的一个子集时,请使用update()方法。

更新表结合了内容值语法的insert()和delete()语法的地方。

SQLiteDatabase db = mDbHelper.getReadableDatabase();// New value for one columnContentValues values = new ContentValues();values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE, title);// Which row to update, based on the IDString selection = FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";String[] selelectionArgs = { String.valueOf(rowId) };int count = db.update(    FeedReaderDbHelper.FeedEntry.TABLE_NAME,    values,    selection,    selectionArgs);