SQLite

定义schema和contract

SQL数据库的一个主要原则就是它的schema:数据库组织方式的正式声明。scheme反映在创建数据库的语句当中。
可以创建一个contract类来协助数据库的创建,一个contract类包含了可复用的URIs、数据表和数据栏的常量定义。组织一个contract类的好做法是把对于整个数据库生效的定义放到类成员变量中,然后为每个数据表创建一个内部类。
contract的内部类通过实现BaseColumns这个接口可以继承_ID这个常量,使用指针适配器要求有这个常量。虽然不是必须实现这个接口,但是实现的话有助于和Android的框架和谐工作。

public final class FeedReaderContract {
    // To prevent someone from accidentally instantiating the contract class,
    // make the constructor private.
    private FeedReaderContract() {}

    /* Inner class that defines the table contents */
    public static class FeedEntry implements BaseColumns {
        public static final String TABLE_NAME = "entry";
        public static final String COLUMN_NAME_TITLE = "title";
        public static final String COLUMN_NAME_SUBTITLE = "subtitle";
    }
}

使用SQL Helper创建数据库

private static final String SQL_CREATE_ENTRIES =
    "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
    FeedEntry._ID + " INTEGER PRIMARY KEY," +
    FeedEntry.COLUMN_NAME_TITLE + " TEXT," +
    FeedEntry.COLUMN_NAME_SUBTITLE + " TEXT)";
	
private static final String SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;

数据库保存在应用的私有内部存储空间中,所以数据是安全的。

使用SQLiteOpenHelper获取数据库的引用,系统会在需要时运行打开或者升级数据库的耗时操作,操作不会在应用启动时进行。我们只需要调用getWritableDatabase() or getReadableDatabase()即可,但是因为可能是耗时操作,所以需要在子线程中运行,可以使用AsyncTask或者IntentService。

使用SQLiteOpenHelper需要创建其子类,复写onCreate(), onUpgrade() 和onOpen()三个回调。

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

保存到数据库

// 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_TITLE, title);
values.put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle);

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

insert()方法的第二个参数为空时,表示当ContentValues为空时(没有put数据进去),不会插入新数据。第二个参数指明某个栏时,会插入一条该栏为null的新数据。

从数据库获取信息

调用query()方法,返回一个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_SUBTITLE
    };

// Filter results WHERE "title" = 'My Title'
String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?";
String[] selectionArgs = { "My Title" };

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

Cursor cursor = 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:调用moveToNext()方法移动指针。cursor.getString()或者getLong()等方法查询数据,传入所查询数据的index,可以使用cursor.getColumnIndex()或者cursor.getColumnIndexOrThrow()方法获取index。

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

从数据库中删除信息

要从数据库中删除一条数据,需要指明区分出该条数据的筛选条件。数据库API提供了一种避免SQL注入危险的创建筛选条件方式。

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

数据库升级

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 title
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
String[] selectionArgs = { "MyTitle" };

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

数据库连接持久使用

因为 getWritableDatabase()和getReadableDatabase()调用比较耗时,所以应该尽量在需要使用时保持数据库的开启状态,比如在使用到数据库的Activity的onDestroy()中

@Override
protected void onDestroy() {
    mDbHelper.close();
    super.onDestroy();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值