前言:
上一篇简介了greendao的数据库的接入以及简单的操作,既然涉及到数据库中的数据,那就必须考虑到加密问题了,可能有些隐秘的数据不能直接加密,我们就需要使用加密了。一旦我们数据库结构改变了,我们就需要使用数据库更新了。
一:数据库加密
我们这里使用sqlcipher加密greendao数据库:
1:在使用GreenDao的Moudle中添加依赖:
//数据库加密库
compile'net.zetetic:android-database-sqlcipher:3.5.6'
2:在初始化数据库中我们只需要获取一个加密的数据库即可
/**
*配置数据库
*/
//数据库是否加密
public static final boolean ENCRYPTED=false;
private voidsetupDatabase() {
//创建数据库book.db"
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "book.db", null);
//获取可写数据库 如果ENCRYPTED=true获取加密数据库 password为加密的密码
Database db =ENCRYPTED? helper.getEncryptedWritableDb("password") : helper.getWritableDb();
//获取数据库对象
DaoMaster daoMaster =newDaoMaster(db);
//获取Dao对象管理者
daoSession= daoMaster.newSession();
}
只需要以上2步我们就完成了对数据库的加密
二:对GreenDao数据库进行升级
在greendao数据库初始化的过程中我们使用的是DaoMaster.DevOpenHelper来获取helper对象来创建数据库:我们可以看到里面的源码:
上面我们可以看到WARNING:更新会删除所有的数据库重写创建,并不会保存之前的数据库数据,因此只是有与开发阶段使用。
因此我们在项目上线之后我们就不能使用这种方式创建数据库了,我们需要做的是自己创建一个OpenHelper去创建数据库,在onUpgrade方法中恢复数据:
1:创建一个和原来表一样的临时表
2:删除之前的数据库,并且创建新的数据库。
3:最后恢复临时表的数据到新的数据库中
这样就可以保证数据库里面的数据不会被删除了。
1:创建MergeOpenHelper继承自OpenHelper
public class MergeOpenHelper extends DaoMaster.OpenHelper {
public MergeOpenHelper(Context context,String name) {
super(context,name);
}
public MergeOpenHelper(Context context,String name,SQLiteDatabase.CursorFactory factory) {
super(context,name,factory);
}
@Override
public voidon Upgrade(Database db, intoldVersion, intnewVersion) {
//super.onUpgrade(db, oldVersion, newVersion);
MigrationHelper.getInstance().migrate(db,UserDao.class,PersonDao.class,BookDao.class);
}
}
2:创建一个合并类,这里拷贝一份大神的代码:
public classMigrationHelper{
private static fina lString CONVERSION_CLASS_NOT_FOUND_EXCEPTION="MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";
private static MigrationHelper instance;
public static MigrationHelper getInstance() {
if(instance==null) {
instance=new MigrationHelper();
}
return instance;
}
private static ListgetColumns(Database db,String tableName) {
List columns =new ArrayList<>();
Cursor cursor =null;
try{
cursor = db.rawQuery("SELECT * FROM "+ tableName +" limit 1", null);
if(cursor !=null) {
columns =new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
}
}catch(Exception e) {
Log.v(tableName,e.getMessage(),e);
e.printStackTrace();
}finally{
if(cursor !=null)
cursor.close();
}
returncolumns;
}
public void migrate(Database db,Class>... daoClasses) {
generateTempTables(db,daoClasses);
DaoMaster.dropAllTables(db, true);
DaoMaster.createAllTables(db, false);
restoreData(db,daoClasses);
}
private void generateTempTables(Database db,Class>... daoClasses) {
for(inti =0;i < daoClasses.length;i++) {
DaoConfig daoConfig =new DaoConfig(db,daoClasses[i]);
String divider ="";
String tableName = daoConfig.tablename;
String tempTableName = daoConfig.tablename.concat("_TEMP");
ArrayList properties =newArrayList<>();
StringBuilder createTableStringBuilder =newStringBuilder();
createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");
for(intj =0;j < daoConfig.properties.length;j++) {
String columnName = daoConfig.properties[j].columnName;
if(getColumns(db,tableName).contains(columnName)) {
properties.add(columnName);
String type =null;
try{
type = getTypeByClass(daoConfig.properties[j].type);
}catch(Exception exception) {
exception.printStackTrace();
}
createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);
if(daoConfig.properties[j].primaryKey) {
createTableStringBuilder.append(" PRIMARY KEY");
}
divider =",";
}
}
createTableStringBuilder.append(");");
db.execSQL(createTableStringBuilder.toString());
StringBuilder insertTableStringBuilder =newStringBuilder();
insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
insertTableStringBuilder.append(TextUtils.join(",",properties));
insertTableStringBuilder.append(") SELECT ");
insertTableStringBuilder.append(TextUtils.join(",",properties));
insertTableStringBuilder.append(" FROM ").append(tableName).append(";");
db.execSQL(insertTableStringBuilder.toString());
}
}
private void restoreData(Database db,Class>... daoClasses) {
for(inti =0;i < daoClasses.length;i++) {
DaoConfig daoConfig =new DaoConfig(db,daoClasses[i]);
String tableName = daoConfig.tablename;
String tempTableName = daoConfig.tablename.concat("_TEMP");
ArrayList properties =new ArrayList();
ArrayList propertiesQuery =new ArrayList();
for(intj =0;j < daoConfig.properties.length;j++) {
String columnName = daoConfig.properties[j].columnName;
if(getColumns(db,tempTableName).contains(columnName)) {
properties.add(columnName);
propertiesQuery.add(columnName);
}else{
try{
if(getTypeByClass(daoConfig.properties[j].type).equals("INTEGER")) {
propertiesQuery.add("0 as "+ columnName);
properties.add(columnName);
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
StringBuilder insertTableStringBuilder =newStringBuilder();
insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
insertTableStringBuilder.append(TextUtils.join(",",properties));
insertTableStringBuilder.append(") SELECT ");
insertTableStringBuilder.append(TextUtils.join(",",propertiesQuery));
insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");
StringBuilder dropTableStringBuilder =newStringBuilder();
dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
db.execSQL(insertTableStringBuilder.toString());
db.execSQL(dropTableStringBuilder.toString());
}
}
privateStringgetTypeByClass(Class type)throwsException {
if(type.equals(String.class)) {
return"TEXT";
}
if(type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class) || type.equals(int.class)) {
return"INTEGER";
}
if(type.equals(Boolean.class) || type.equals(boolean.class)) {
return"BOOLEAN";
}
Exception exception =newException(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));
exception.printStackTrace();
throwexception;
}
}
3:修改初始化数据库代码
/**
*配置数据库
*/
private voidsetupDatabase() {
//创建数据库book.db" 这里使用了升级使用的OpenHelper
MergeOpenHelper helper =newMergeOpenHelper(this,"book.db");
//获取可写数据库
Database db =ENCRYPTED? helper.getEncryptedWritableDb("password") : helper.getWritableDb();
//SQLiteDatabase db = helper.getWritableDatabase();
//获取数据库对象
DaoMaster daoMaster =newDaoMaster(db);
//获取Dao对象管理者
daoSession= daoMaster.newSession();
}
4:修改我们在build.gradle中数据库版本增加(只能加不能减)。
schemaVersion 7//指定数据库schema版本号,迁移等操作会用到