android数据库使用情景:  在android客户端,对于一些大量 复杂并且反复操作的数据,适合存储在数据库如同  通讯录信息。 而对于一些 简单数据如 标记 登录次数等 可以考虑用SharePreference。

         (同样android底层还是运用基本的SQL语言操作数据库。 android数据库  API 在 android.database.sqlite包内)


第一步:  定义数据库的基本架构以及约定

 

            为创建的数据库建立一个架构 ---  规范的声明 : 数据库的组织结构  数据库名 ---  表 ---- 字段(cloumn) 三重结构的每部分。 

          

            这个架构类几乎包含数据库中的所有常量,声明URIs的名字,表、列等基本结构。 这样做的效果可以使得在数据库操作的整个阶段共用这些常量,使得对于数据库字段等名字日后的修改变得简单,只需修改一处常量即可。

            如何表示这三层结构呢? 类代表了数据库,类中的常量作为数据库全局的变量,使用内部类去代表数据库的每一个表格,内部类中常量代表各个字段。

             android数据库中大多数地方要求有约定_ID主键,此时内部类通过继承BaseColumns接口,获得这个字段,使得你建立的数据库更加适应于android框架。

            如下代码段,声明数据库以及该数据库中的一张表结构。

public final class FeedReaderContract {
    // To prevent someone from accidentally instantiating the contract class,
    // give it an empty constructor.
    public FeedReaderContract() {}

    /* Inner class that defines the table contents */
    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";
        ...
    }
}

 


第二步  建立数据库(使用SQL helper)


     通过架构类声明好的结构后,我们就要去创建保存数据库以及表格。  作为一个良好设计(^-^),我们又需要声明一系列创建数据库表经常使用的语句常量:

    比如:

private static final String TEXT_TYPE = " TEXT";
private static final String COMMA_SEP = ",";
private static final String SQL_CREATE_ENTRIES =
    "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
    FeedEntry._ID + " INTEGER PRIMARY KEY," +
    FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP +
    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 " + FeedEntry.TABLE_NAME;

        在android框架里SQLiteOpenHelper 类提供一系列简单快捷的数据库操作API。这就是数据库操作中的主角。

        当你使用这个方法去获得对数据库的引用时,系统后台框架做了一些耗时的操作去创建或更新数据库,而不是默认直接在应用打开时获得。而你需要做的就是调用这个类的 getWritableDatabase()或是getReadableDatabase() 获得对于数据库引用,这样你应该把这个调用放到后台线程进行,比如AsyncTask或者IntentService中,而不是UI线程傻傻等待。

       要使用SQLiteOpenHelper, 通过创建一个子类必须覆盖该类的onCreate(),onUpgrade()和onOpen()这些回调方法,和可覆盖的方法onDownGrad()  (数据库回溯)

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);
    }
}



     接下来实例化该类,使得你可以获得数据库的引用。

FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext());

 所以真正创建过程在android框架中进行,我们只需调用mDbHelper.getWritableDatabase()方法,系统会回调相应的OnCreate或者onUpgrade方法执行相应的SQL语句创建数据库。同样这些操作会在 一块与你应用相关联的存储区域建立数据库文件 db 即 /data/data/包名/db 文件目录下。为了保证数据安全性,其他应用不能访问到这些文件。



   第三步  数据库数据的数据操作:

    android通过SQLiteDatabase提供封装好的数据库数据操作API。通过一些直接的参数,从而对数据库进行复杂操作。

     1 数据的插入: 通过contentValues 类似键值对的对象作为载体(key为列名,value是插入的值),insert()方法执行插入,不罗嗦直接看代码—一目了然

 

// Gets the data repository in write mode
SQLiteDatabase db = mDbHelper.getWritableDatabase();

// Create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
values.put(FeedEntry.COLUMN_NAME_CONTENT, content);

// Insert the new row, returning the primary key value of the new row
long newRowId;
newRowId = db.insert(
         FeedEntry.TABLE_NAME,
         FeedEntry.COLUMN_NAME_NULLABLE,
         values);



关于insert的第二个参数 代表 nullColumnHack ,可以为空,或者是一个列名,因为对于空的contentValues对象时,SQL语句插入时没有列名和值时,使得不能插入数据。

所以当你需要在value为空时,也能够插入一条空的记录,提供任意一个列名给这个方法。

 

     2 读取数据

    使用qury() 方法,传递查询条件和返回列 , 返回结果是一个cursor对象。

SQLiteDatabase db = mDbHelper.getReadableDatabase();

// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
    FeedEntry._ID,
    FeedEntry.COLUMN_NAME_TITLE,
    FeedEntry.COLUMN_NAME_UPDATED,
    ...
    };

// How you want the results sorted in the resulting Cursor
String sortOrder =
    FeedEntry.COLUMN_NAME_UPDATED + " DESC";

Cursor c = db.query(
    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对象后,要想查看到结果集行,必须先调用cursor的move方法移到某个位置进行读取。  一般使用moveToFirst()方法将读取位置对应于结果的首行。然后对于  每行,调用cursor的get方法获取列值如getString(int index),getLong(int index),其中参数代表了列的索引通过 getColumnIndex(columnName)获得。比如:

cursor.moveToFirst();
long itemId = cursor.getLong(
    cursor.getColumnIndexOrThrow(FeedEntry._ID)
);




    3   删除数据

   你需要提供选择条件去删除特定的行。系统提供创建条件语句方法  以保证SQL语句的注入。这个方法 将选择条件分为 选择语句 和 选择参数俩部分。 选择语句声明选择的一列或者多列,而选择参数提供相应列的值。

 

// Define 'where' part of query.
String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
// Specify arguments in placeholder order.
String[] selectionArgs = { String.valueOf(rowId) };
// Issue SQL statement.
db.delete(table_name, selection, selectionArgs);



    4  更新数据


     使用update方法修改数据库中的子集。  

SQLiteDatabase db = mDbHelper.getReadableDatabase();

// New value for one column
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);

// Which row to update, based on the ID
String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
String[] selectionArgs = { String.valueOf(rowId) };

int count = db.update(
    FeedReaderDbHelper.FeedEntry.TABLE_NAME,
    values,
    selection,
    selectionArgs);