微信 WCDB 正式開源——高效易用的移動數據庫框架

前沿介紹

騰訊開源微信數據庫框架WCDB,他是一個高效、完整、易用的移動數據庫框架,基於SQLCipher,支持iOS, macOS和Android。android

便捷地定義表、索引、約束,並進行增刪改查操做

項目演示效果以下:git

Markdown
Markdown

微信 即時通信軟件

  • 微信(英文名:wechat)是騰訊公司於2011年1月21日推出的一個爲智能終端提供即時通信服務的免費應用程序github

  • 微信支持跨通訊運營商、跨操做系統平臺經過網絡快速發送免費語音短信、視頻、圖片和文字sql

  • 同時,也可使用經過共享流媒體內容的資料和基於位置的社交插件「搖一搖」、「漂流瓶」、「朋友圈」、」公衆平臺「、」語音記事本「等服務插件。數據庫

  • 騰訊於6月9日在 GMTC 全球移動技術大會上正式宣佈, WCDB(WeChat Database)做爲微信的一個開源組件正式對外開源bash

基本功能

Markdown
Markdown

  • 基於SQLCipher的數據庫加密微信

  • 使用鏈接池實現併發讀寫網絡

  • 內建 Repair Kit 可用於修復損壞數據庫多線程

  • 針對佔用空間大小優化的數據庫備份/恢復功能架構

  • 日誌輸出重定向以及性能跟蹤接口

  • 內建用於全文搜索的 mmicu FTS3/4 分詞器
    入門

官方介紹以下:

WCDB 是一個高效、完整、易用的移動數據庫框架,基於 SQLCipher,支持 iOS、macOS 和 Android。

WCDB的好處

  • WINQ(WCDB語言集成查詢): 經過WINQ,開發者無須爲了拼接SQL的字符串而寫一大坨膠水代碼。

  • ORM(Object Relational Mapping): WCDB支持靈活、易用的ORM。開發者能夠很便捷地定義表、索引、約束,並進行增刪改查操做。

  • 多線程高併發: WCDB支持多線程讀與讀、讀與寫併發執行,寫與寫串行執行。

  • 加密:WCDB提供基於SQLCipher的數據庫加密。

  • 損壞修復: WCDB內建了Repair Kit用於修復損壞的數據庫。

  • 反注入: WCDB內建了對SQL注入的保護。

  • 基於SQLCipher的數據庫加密

  • 使用鏈接池實現併發讀寫

  • 內建 Repair Kit 可用於修復損壞數據庫

  • 針對佔用空間大小優化的數據庫備份/恢復功能

  • 日誌輸出重定向以及性能跟蹤接口

  • 內建用於全文搜索的 mmicu FTS3/4 分詞器

相關代碼(SQLiteOpenHelper類)

/**
     * 類功能描述:</br>
     * 新數據處理幫助類
     * @author 於亞豪
     *  博客地址: http://blog.csdn.net/androidstarjack
     * 公衆號: 終端研發部
     * @version 1.0 </p> 修改時間:</br> 修改備註:</br>
     */
public class EncryptedDBHelper extends SQLiteOpenHelper {

        private static final String TAG = "EncryptedDBHelper";

        private static final String DATABASE_NAME = "encrypted.db";
        private static final String OLD_DATABASE_NAME = "plain-text.db";
        private static final int DATABASE_VERSION = 2;

        private Context mContext;
        private String mPassphrase;

        public EncryptedDBHelper(Context context, String passphrase) {

            // 調用「加密」版本的超類構造函數。
            super(context, DATABASE_NAME, passphrase.getBytes(), null, null, DATABASE_VERSION,
                    null);
            // 保存上下文對象供之後使用。
            mContext = context;
            mPassphrase = passphrase;
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            // 檢查數據庫plain-text.db是否存在 ,存在 若是是這樣,將其導出到新的加密庫中的。
            File oldDbFile = mContext.getDatabasePath(OLD_DATABASE_NAME);
            if (oldDbFile.exists()) {

                Log.i(TAG, "Migrating plain-text database to encrypted one.");

                //SQLiteOpenHelper在調用onCreate()以前開始一個事務。 咱們必須結束事務才能附加一個新的數據庫。
                db.endTransaction();

                // 將舊數據庫附加到新建立的加密數據庫。
                String sql = String.format("ATTACH DATABASE %s AS old KEY '';",
                        DatabaseUtils.sqlEscapeString(oldDbFile.getPath()));
                db.execSQL(sql);

                // 導出舊數據庫。
                db.beginTransaction();
                DatabaseUtils.stringForQuery(db, "SELECT sqlcipher_export('main', 'old');", null);
                db.setTransactionSuccessful();
                db.endTransaction();

                // 獲取舊的數據庫版本供之後升級。
                int oldVersion = (int) DatabaseUtils.longForQuery(db, "PRAGMA old.user_version;", null);

                // 分離舊數據庫並輸入新的事務。
                db.execSQL("DETACH DATABASE old;");

                // 舊數據庫如今能夠刪除。
                oldDbFile.delete();

                // 在進一步的操做以前,還原事務。
                db.beginTransaction();

                // 檢查咱們是否須要升級架構。
                if (oldVersion > DATABASE_VERSION) {
                    onDowngrade(db, oldVersion, DATABASE_VERSION);
                } else if (oldVersion < DATABASE_VERSION) {
                    onUpgrade(db, oldVersion, DATABASE_VERSION);
                }
            } else {
                Log.i(TAG, "Creating new encrypted database.");

                // 若是舊數據庫不存在,請進行真正的初始化。
                db.execSQL("CREATE TABLE message (content TEXT, "
                        + "sender TEXT);");
            }

            // 損壞恢復的備份主信息。
            RepairKit.MasterInfo.save(db, db.getPath() + "-mbak", mPassphrase.getBytes());
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

            Log.i(TAG, String.format("Upgrading database from version %d to version %d.",
                    oldVersion, newVersion));

            //將新列添加到數據庫升級的消息表中。
            db.execSQL("ALTER TABLE message ADD COLUMN sender TEXT;");

            //損壞恢復的備份主信息
            RepairKit.MasterInfo.save(db, db.getPath() + "-mbak", mPassphrase.getBytes());
        }
    }複製代碼

WCDB如何查詢數據庫的相關示例:

new AsyncTask<Void, Void, Cursor>() {
            @Override
            protected void onPreExecute() {
                mAdapter.notifyDataSetChanged();
            }
            @Override
            protected Cursor doInBackground(Void... params) {
                if (mDB == null || !mDB.isOpen())
                    return null;

                String message = "Message inserted on " + DATE_FORMAT.format(new Date());

                if (mDBVersion == 1) {
                    mDB.execSQL("INSERT INTO message VALUES (?);",
                            new Object[]{"yyh"});
                    return mDB.rawQuery("SELECT rowid as _id, content, '???' as sender FROM message;",
                            null);
                } else {
                    mDB.execSQL("INSERT INTO message VALUES (?, ?);",
                            new Object[]{"yyh", "男"});
                    return mDB.rawQuery("SELECT rowid as _id, content, sender FROM message;",
                            null);
                }
            }
            @Override
            protected void onPostExecute(Cursor cursor) {
                if (cursor == null)
                    return;
                list = getAllStudent(cursor);
                mAdapter.changeCursor(list);
            }
        }.execute();複製代碼

WWCDB如何插入表的相關示例:

final DateFormat DATE_FORMAT = SimpleDateFormat.getDateTimeInstance();
        new AsyncTask<Void, Void, Cursor>() {
            @Override
            protected void onPreExecute() {
                mAdapter.notifyDataSetChanged();
            }
            @Override
            protected Cursor doInBackground(Void... params) {
                if (mDB == null || !mDB.isOpen())
                    return null;

                String message = "Message inserted on " + DATE_FORMAT.format(new Date());

                if (mDBVersion == 1) {
                    mDB.execSQL("INSERT INTO message VALUES (?);",
                            new Object[]{"yyh"});
                    return mDB.rawQuery("SELECT rowid as _id, content, '???' as sender FROM message;",
                            null);
                } else {
                    mDB.execSQL("INSERT INTO message VALUES (?, ?);",
                            new Object[]{"yyh", "男"});
                    return mDB.rawQuery("SELECT rowid as _id, content, sender FROM message;",
                            null);
                }
            }
            @Override
            protected void onPostExecute(Cursor cursor) {
                if (cursor == null)
                    return;
                list = getAllStudent(cursor);
                mAdapter.changeCursor(list);
            }
        }.execute();複製代碼

WCDB如何刪除表的相關示例:

if (mDB == null || !mDB.isOpen()){
        return  ;

    }
    mDB.execSQL("DELETE FROM message WHERE content"+"=?",new Object[]{"yyh"});
    com.tencent.wcdb.Cursor cursor =  mDB.rawQuery("SELECT rowid as _id, content, sender FROM message;",null);
    list = getAllStudent(cursor);
    mAdapter.changeCursor(list);複製代碼

完整demo下載地址:

相關項目下載地址(github):

github.com/androidstar…

csdn下載連接
download.csdn.net/detail/andr…

關於WCDB還有不少的地方要去學習,該demo中只是演示的其中的冰山一角,接下來咱們還有不少要探尋的。

WCDB官方地址:

WCDB官方地址

github.com/Tencent/wcd…

相信本身,沒有作不到的,只有想不到的

若是你以爲此文對您有所幫助,歡迎入羣 QQ交流羣 :232203809
微信公衆號:終端研發部

Markdown
Markdown

(這裏 學到的不單單是技術)

相關文章
相關標籤/搜索