前沿介紹
騰訊開源微信資料庫框架WCDB,他是一個高效、完整、易用的移動資料庫框架,基於SQLCipher,支援iOS, macOS和Android。
便捷地定義表、索引、約束,並進行增刪改查操作
專案演示效果如下:
微信 即時通訊軟體
微信(英文名:wechat)是騰訊公司於2011年1月21日推出的一個為智慧終端提供即時通訊服務的免費應用程式
微信支援跨通訊運營商、跨作業系統平臺通過網路快速傳送免費語音簡訊、視訊、圖片和文字
同時,也可以使用通過共享流媒體內容的資料和基於位置的社交外掛“搖一搖”、“漂流瓶”、“朋友圈”、”公眾平臺“、”語音記事本“等服務外掛。
騰訊於6月9日在 GMTC 全球移動技術大會上正式宣佈, WCDB(WeChat Database)作為微信的一個開源元件正式對外開源
基本功能
基於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):
csdn下載連結
download.csdn.net/detail/andr…
關於WCDB還有很多的地方要去學習,該demo中只是演示的其中的冰山一角,接下來我們還有很多要探尋的。
WCDB官方地址:
WCDB官方地址
相信自己,沒有做不到的,只有想不到的
如果你覺得此文對您有所幫助,歡迎入群 QQ交流群 :232203809
微信公眾號:終端研發部
(這裡 學到的不僅僅是技術)