腾讯开源微信数据库框架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
微信公众号:终端研发部
(这里 学到的不单单是技术)