Android SQLite 使用方法(含完整案例)

目录

1. Demo展示

2. 实现方法

 2.1 定义数据库的结构

2.2 使用SQLiteHelper来创建数据库

3. 注意事项


1. Demo展示

Demo 案例:实现联系人列表功能,我们可以增加联系人,修改联系人,删除联系人,以及根据联系人的名字查询该联系人的功能,如下图所示:

增加联系人
查询联系人
修改联系人
删除联系人

2. 实现方法

app 的结构如下:(源码见 -> Android_SQLite_Learning)

Android SQLite 使用方法(含完整案例)_第1张图片

 2.1 定义数据库的结构

package com.jere.android_sqlite_learning.model;

/**
 * @author jere
 */
public class BusinessCard {
    public static final String TABLE_NAME = "BusinessCard";
    public static final String COLUMN_ID = "id";
    public static final String COLUMN_AVATAR = "avatar";
    public static final String COLUMN_NAME = "name";
    public static final String COLUMN_GENDER = "gender";
    public static final String COLUMN_TELEPHONE = "telephone";
    public static final String COLUMN_ADDRESS = "address";

    public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "("
            + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
            + COLUMN_NAME + " TEXT,"
            + COLUMN_GENDER + " INTEGER,"
            + COLUMN_AVATAR + " INTEGER,"
            + COLUMN_TELEPHONE + " TEXT,"
            + COLUMN_ADDRESS + " TEXT"
            + ")";

    private int id;
    private int avatar;
    private String name;
    private String telephone;
    //true:male, false:female
    private boolean gender;
    private String address;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAvatar() {
        return avatar;
    }

    public void setAvatar(int avatar) {
        this.avatar = avatar;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean getGender() {
        return gender;
    }

    public void setGender(boolean gender) {
        this.gender = gender;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

2.2 使用SQLiteHelper来创建数据库

/**
 * @author jere
 */
public class DataBaseHelper extends SQLiteOpenHelper {
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "business_card_db";

    public DataBaseHelper(@Nullable Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL(BusinessCard.CREATE_TABLE);

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        //drop old table if is existed
        sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + BusinessCard.TABLE_NAME);
        //create table again
        onCreate(sqLiteDatabase);
    }

    /**
     *
     * @param businessCard
     * @return 返回新插入的行的ID,发生错误,插入不成功,则返回-1
     */
    public long insertBusinessCard(BusinessCard businessCard) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(BusinessCard.COLUMN_AVATAR, businessCard.getGender() ? R.drawable.male_avatar_icon : R.drawable.female_avatar_icon);
        values.put(BusinessCard.COLUMN_NAME, businessCard.getName());
        values.put(BusinessCard.COLUMN_GENDER, businessCard.getGender() ? 1 : 0);
        values.put(BusinessCard.COLUMN_TELEPHONE, businessCard.getTelephone());
        values.put(BusinessCard.COLUMN_ADDRESS, businessCard.getAddress());
        long id = db.insert(BusinessCard.TABLE_NAME, null, values);
        db.close();
        return id;
    }

    /**
     *
     * @param searchName query database by name
     * @return BusinessCard
     */
    public BusinessCard getBusinessCardQueryByName(String searchName) {
        BusinessCard businessCard = new BusinessCard();
        SQLiteDatabase db = this.getReadableDatabase();
        String[] columnArray = new String[]{
                BusinessCard.COLUMN_ID,
                BusinessCard.COLUMN_NAME,
                BusinessCard.COLUMN_GENDER,
                BusinessCard.COLUMN_AVATAR,
                BusinessCard.COLUMN_TELEPHONE,
                BusinessCard.COLUMN_ADDRESS};
        Cursor cursor = db.query(BusinessCard.TABLE_NAME,
                columnArray,
                BusinessCard.COLUMN_NAME + "=? ",
                new String[]{searchName},
                null, null, null);
        if (cursor != null && cursor.moveToNext()) {
            int id = cursor.getInt(cursor.getColumnIndex(BusinessCard.COLUMN_ID));
            String name = cursor.getString(cursor.getColumnIndex(BusinessCard.COLUMN_NAME));
            int portrait = cursor.getInt(cursor.getColumnIndex(BusinessCard.COLUMN_AVATAR));
            String telephone = cursor.getString(cursor.getColumnIndex(BusinessCard.COLUMN_TELEPHONE));
            String address = cursor.getString(cursor.getColumnIndex(BusinessCard.COLUMN_ADDRESS));
            int gender = cursor.getInt(cursor.getColumnIndex(BusinessCard.COLUMN_GENDER));
            businessCard.setId(id);
            businessCard.setName(name);
            businessCard.setAvatar(portrait);
            businessCard.setTelephone(telephone);
            businessCard.setAddress(address);
            businessCard.setGender(gender == 1);

            cursor.close();
            return businessCard;
        }
        return null;
    }

    /**
     *
     * @return 读取数据库,返回一个 BusinessCard 类型的 ArrayList
     */
    public ArrayList getAllBusinessCards() {
        ArrayList businessCardsList = new ArrayList<>();

        String selectQuery = "SELECT * FROM " + BusinessCard.TABLE_NAME
                + " ORDER BY " + BusinessCard.COLUMN_ID + " ASC";
        SQLiteDatabase db = getReadableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);
        if (cursor != null) {
            while (cursor.moveToNext()) {
                BusinessCard businessCard = new BusinessCard();
                int id = cursor.getInt(cursor.getColumnIndex(BusinessCard.COLUMN_ID));
                String name = cursor.getString(cursor.getColumnIndex(BusinessCard.COLUMN_NAME));
                int portrait = cursor.getInt(cursor.getColumnIndex(BusinessCard.COLUMN_AVATAR));
                String telephone = cursor.getString(cursor.getColumnIndex(BusinessCard.COLUMN_TELEPHONE));
                String address = cursor.getString(cursor.getColumnIndex(BusinessCard.COLUMN_ADDRESS));
                int gender = cursor.getInt(cursor.getColumnIndex(BusinessCard.COLUMN_GENDER));
                businessCard.setId(id);
                businessCard.setName(name);
                businessCard.setAvatar(portrait);
                businessCard.setTelephone(telephone);
                businessCard.setAddress(address);
                businessCard.setGender(gender == 1);

                businessCardsList.add(businessCard);
            }
        }

        db.close();
        return businessCardsList;
    }

    /**
     *
     * @return 返回数据库行数
     */
    public int getBusinessCardCount() {
        String countQuery = "SELECT * FROM " + BusinessCard.TABLE_NAME;
        SQLiteDatabase db = getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);
        int count = cursor.getCount();
        cursor.close();
        return count;
    }

    /**
     *
     * @param id update row id (需要更新的ID)
     * @param businessCard update value (去更新数据库的内容)
     * @return the number of rows affected (影响到的行数,如果没更新成功,返回0。所以当return 0时,需要告诉用户更新不成功)
     */
    public int updateBusinessCard(int id, BusinessCard businessCard) {
        SQLiteDatabase db = getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(BusinessCard.COLUMN_AVATAR, businessCard.getAvatar());
        values.put(BusinessCard.COLUMN_NAME, businessCard.getName());
        values.put(BusinessCard.COLUMN_TELEPHONE, businessCard.getTelephone());
        values.put(BusinessCard.COLUMN_ADDRESS, businessCard.getAddress());
        values.put(BusinessCard.COLUMN_GENDER, businessCard.getGender() ? 1 : 0);
        int idReturnByUpdate = db.update(BusinessCard.TABLE_NAME, values, BusinessCard.COLUMN_ID + " =? ", new String[]{String.valueOf(id)});
        db.close();
        return idReturnByUpdate;
    }

    /**
     *
     * @param id the database table row id need to delete(需要删除的数据库表中行的ID)
     * @return 返回影响到的行数,如果在 whereClause 有传入条件,返回该条件下影响到的行数,否则返回0。
     * 想要删除所有行,只要在 whereClause 传入 String "1",并返回删除掉的行数总数(比如:删除了四行就返回4)
     */
    public int deleteBusinessCard(int id) {
        SQLiteDatabase db = getWritableDatabase();
        int idReturnByDelete = db.delete(BusinessCard.TABLE_NAME, BusinessCard.COLUMN_ID + "=? ", new String[]{String.valueOf(id)});
        db.close();
        return idReturnByDelete;
    }

    /**
     * 删除所有行,whereClause 传入 String "1"
     * @return 返回删除掉的行数总数(比如:删除了四行就返回4)
     */
    public int deleteAllBusinessCard() {
        SQLiteDatabase db = getWritableDatabase();
        int idReturnByDelete = db.delete(BusinessCard.TABLE_NAME, String.valueOf(1), null);
        db.close();
        return idReturnByDelete;
    }
}

3. SQLite 升级版本

在上方的 Demo 中 onUpgrade() 方法中我们可以发现,当数据库升级时我们采用了最简单粗暴的方法,删除重建表,但在实际开发中需要严谨的对待数据库migration,一旦造成用户数据丢失,将是很差的用户体验。

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
    /**在很多Demo中为了简单,直接删除重建表
    //drop old table if is existed
    sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + BusinessCard.TABLE_NAME);
    //create table again
    onCreate(sqLiteDatabase); **/

    //但在实际开发中需要严谨的对待数据库migration,一旦造成用户数据丢失,是很差的用户体验。
    if (oldVersion < 2) {
        upgradeVersion2(sqLiteDatabase);
    }
}

private void upgradeVersion2(SQLiteDatabase db) {
    db.execSQL("ALTER TABLE " + BusinessCard.TABLE_NAME + " ADD COLUMN " + BusinessCard.COLUMN_COMMENT + " TEXT");
}

/** 而且实际开发中,要面对着很多的升级,从1升到2,然后2到3,3到4. **/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (oldVersion < 2) {
         db.execSQL(upgradeDatabaseToVersion2Sql);
    }
    if (oldVersion < 3) {
         db.execSQL(upgradeDatabaseToVersion3Sql);
    }
    if (oldVersion < 4) {
         db.execSQL(upgradeDatabaseToVersion4Sql);
    }
}

关于 onUpgrade() 方法,官方说法是:

/**
在数据库版本升高时就会被触发,即在数据库需要升级时调用。使用此方法来做删除表、添加表或执行升级到新数据库结构版本所需的任何其他操作,从而实现升级。
关于 ALTER TABLE 的操作可以点击“http://sqlite.org/lang_altertable.html”链接来查看详细内容,如果添加新列,可以使用ALTER TABLE将它们插入活动表。如果重命名或删除列,可以使用ALTER TABLE重命名旧表,然后创建新表,然后用旧表的内容填充新表。
这个方法在一个事务中执行。如果抛出异常,所有更改将自动回滚。
 * @param db The database.
 * @param oldVersion The old database version.
 * @param newVersion The new database version.
 */
public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);

4. SQLite 降级版本

有升级就有降级,当然在实际应用中使用的很少,比如:我们将 DATABASE_VERSION 从 3 改为 2 , 自动触发 onDowngrade() 方法,如下所示:

//测试一下回滚DB, 数据库降级,数据库版本从3降到2
    @Override
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (oldVersion > 2) { //DATABASE_VERSION == 3
            db.execSQL("DROP TABLE IF EXISTS company");
        }
//        super.onDowngrade(db, oldVersion, newVersion);
    }

5. 注意事项

因为数据库的操作是耗时操作,所以你不应该在主线程中进行数据库的操作,将 getWritableDatabase() 和 getReadableDatabase() 放到后台线程中处理,比如利用 AsyncTask 或 IntentService 来进行数据库的操作。如下利用 AsyncTask 来进行删除的操作:

private static class DeleteBusinessCardAsyncTask extends AsyncTask {

    private WeakReference contextWeakReference;

    DeleteBusinessCardAsyncTask(Context context) {
        contextWeakReference = new WeakReference<>(context);
    }

    @Override
    protected Void doInBackground(Integer... integers) {
        Context context = contextWeakReference.get();
        if (context != null) {
            new DataBaseHelper(context).deleteBusinessCard(integers[0]);
        }
        return null;
    }
}

 

源码见 -> Android_SQLite_Learning

你可能感兴趣的:(Android,数据存储)