Android数据库开发实战


我们在Android开发中,如果需要本地持久化数据,可以采用SP、数据库、本地文件等方式。SP适合小数据的存取、数据库查询修改方面非常适合、文件存储适合大数据文件的操作。

那么如何在Android中使用数据库呢?

SQLiteOpenHelper类介绍

SQLiteOpenHelper类可以帮助我们很方便的操作数据库。

SQLiteOpenHelper类包含一组用于管理数据库的实用API。当使用此类获取对数据库的引用时,系统仅在需要时才执行可能需要长时间运行的数据库创建和更新操作,而不是在应用启动期间执行。

可以调用getWritableDatabase()或getReadableDatabase() 方法获取数据库对象。

注意:由于这些操作可能会长时间运行,因此请务必在后台线程中调用 getWritableDatabase() 或 getReadableDatabase()。

创建SQLiteOpenHelper类

我们要使用数据,首先需要新建一个SQLiteOpenHelper类的子类,并且重写onCreate()和onUpgrade()回调方法,可能还需要实现onDowngrade()或onOpen()方法,但这些方法并非必需。

代码示例:

public class SQLiteDbHelp extends SQLiteOpenHelper {
    private static final String SQL_CREATE_ENTRIES =
            "CREATE TABLE " + BookEntry.TABLE_NAME + " (" +
                    BookEntry._ID + " INTEGER PRIMARY KEY," +
                    BookEntry.COLUMN_NAME_TITLE + " TEXT," +
                    BookEntry.COLUMN_NAME_PRICE + " INTEGER)";

    private static final String SQL_DELETE_ENTRIES =
            "DROP TABLE IF EXISTS " + BookEntry.TABLE_NAME;

    public static final String DATABASE_NAME = "budaye_db.db"; //数据库名称
    public static final int DATABASE_VERSION = 1;

    public SQLiteDbHelp(Context context){
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    /**
     * 数据库创建
     * @param db
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE_ENTRIES);
    }

    /**
     * 数据库版本升级
     * @param db
     * @param oldVersion
     * @param newVersion
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(SQL_DELETE_ENTRIES);
        onCreate(db);
    }

    /**
     * 数据库版本降级
     * @param db
     * @param oldVersion
     * @param newVersion
     */
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        onUpgrade(db, oldVersion, newVersion);
    }

}

BookEntry类定义了表名称及相关字段。

public class BookEntry implements BaseColumns {
    public static final String TABLE_NAME = "book";
    public static final String COLUMN_NAME_TITLE = "name";
    public static final String COLUMN_NAME_PRICE = "price";
}

实例化SQLiteOpenHelper的子类

例如,我们在主Activity中,创建它:

    private SQLiteDbHelp dbHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ……
        dbHelper = new SQLiteDbHelp(this.getApplicationContext());
    }

新建SQLiteDbHelp对象之后,我们就可以使用数据库了。

在数据库中插入数据

    private long insertDB(){
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(BookEntry.COLUMN_NAME_TITLE, "Android");
        values.put(BookEntry.COLUMN_NAME_PRICE, 10);
        long newRowId = db.insert(BookEntry.TABLE_NAME, null, values);

        return newRowId;
    }
  1. insert() 的第一个参数就只是表名。
  2. 第二个参数将指示框架在 ContentValues 为空(即您没有 put 任何值)时应执行哪些操作。如果您指定列名称,框架会插入一行,并将该列的值设置为 null。如果您指定 null(如此代码示例所示),框架在没有值时不会插入行。
  3. insert() 方法会返回新创建行的 ID;如果在插入数据时出错,会返回 -1。如果您的数据与数据库中已有的数据之间存在冲突,就会出现这种情况。

从数据库中读取信息

    private void readDB(){
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        String[] projection = {
                BookEntry._ID,
                BookEntry.COLUMN_NAME_TITLE,
                BookEntry.COLUMN_NAME_PRICE
        };
        String selection = BookEntry.COLUMN_NAME_TITLE + " = ?";
        String[] selectionArgs = { "My Title" };

        String sortOrder =
                BookEntry.COLUMN_NAME_PRICE + " DESC";

        Cursor cursor = db.query(
                BookEntry.TABLE_NAME,   // The table to query
                projection,             // The array of columns to return (pass null to get all)
                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
        );

        List itemIds = new ArrayList<>();
        while(cursor.moveToNext()) {
            long itemId = cursor.getLong(
                    cursor.getColumnIndexOrThrow(BookEntry._ID));
            itemIds.add(itemId);
        }
        cursor.close();
    }

第三个参数和第四个参数(selection 和 selectionArgs)会合并起来创建一个 WHERE 子句。由于这两个参数是与选择查询分开提供的,因此它们在合并之前会进行转义。这样一来,您的选择语句就不受 SQL 注入的影响。

从数据库中删除信息

如需从表中删除行,您需要提供选择条件,以标识 delete() 方法的目标行。该机制与 query() 方法的目标选择参数的工作方式相同。它将选择规范划分为选择子句和选择参数。子句定义要查看的列,并允许您合并列测试。参数是要测试的值,这些值绑定到子句中。由于结果的处理方式与常规 SQL 语句的处理方式不同,因此不受 SQL 注入的影响。

    private void deleteDB(){
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        // Define 'where' part of query.
        String selection = BookEntry.COLUMN_NAME_TITLE + " LIKE ?";
        // Specify arguments in placeholder order.
        String[] selectionArgs = { "MyTitle" };
        // Issue SQL statement.
        int deletedRows = db.delete(BookEntry.TABLE_NAME, selection, selectionArgs);
    }

delete() 方法的返回值表示从数据库中删除的行数。

更新数据库中的信息

    private void updateDB(){
        SQLiteDatabase db = dbHelper.getWritableDatabase();

        // New value for one column
        String title = "MyNewTitle";
        ContentValues values = new ContentValues();
        values.put(BookEntry.COLUMN_NAME_TITLE, title);

        // Which row to update, based on the title
        String selection = BookEntry.COLUMN_NAME_TITLE + " LIKE ?";
        String[] selectionArgs = { "MyOldTitle" };

        int count = db.update(
                BookEntry.TABLE_NAME,
                values,
                selection,
                selectionArgs);
    }

update() 方法的返回值是数据库中受影响的行数。

更多推荐

Android 数据库开发实战(简单易懂+DEMO)