騰訊開源微信數據庫框架WCDB,他是一個高效、完整、易用的移動數據庫框架,基於SQLCipher,支持iOS, macOS和Android。android
項目演示效果以下:git
微信(英文名:wechat)是騰訊公司於2011年1月21日推出的一個爲智能終端提供即時通信服務的免費應用程序github
微信支持跨通訊運營商、跨操做系統平臺經過網絡快速發送免費語音短信、視頻、圖片和文字sql
同時,也可使用經過共享流媒體內容的資料和基於位置的社交插件「搖一搖」、「漂流瓶」、「朋友圈」、」公衆平臺「、」語音記事本「等服務插件。數據庫
騰訊於6月9日在 GMTC 全球移動技術大會上正式宣佈, WCDB(WeChat Database)做爲微信的一個開源組件正式對外開源bash
基於SQLCipher的數據庫加密微信
使用鏈接池實現併發讀寫網絡
內建 Repair Kit 可用於修復損壞數據庫多線程
針對佔用空間大小優化的數據庫備份/恢復功能架構
日誌輸出重定向以及性能跟蹤接口
內建用於全文搜索的 mmicu FTS3/4 分詞器
入門
WCDB 是一個高效、完整、易用的移動數據庫框架,基於 SQLCipher,支持 iOS、macOS 和 Android。
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
微信公衆號:終端研發部
(這裏 學到的不單單是技術)