GreenDao的不足
之前也提到过,greenDao有以下不足:
- greenDao Generator仍然有点笨
- greenDao的DaoMaster对数据库的创建和更新比较笨拙,无法实现智能更新。虽然网上有一个叫做MigrationHelper的解决方案,但仍不够友好。
- greenDao的Property支持的属性有限,不支持default、is null、unique 等属性
- greenDao不支持Property更新,只支持整个对象的更新
由于精力有限,我只会对第2-4点进行改进。
我的改进
针对以上几点,进行了几点改进:
- 支持更多属性设置:如NOT NULL、UNIQUE
- 支持Index配置,定义Index就和定义Property一样简单
- 数据库自动化升级
- 数据库支持属性更新
同时,为了享有后面greenDao开源的维护的成果,我们在保持greenDao独立性的基础上进行了扩展,而不进行修改。
因此,进行如下设计:
DaoPropery
我们扩展了Propery,丰富property的属性
public final int ordinal; //索引
public final Class<?> type; //类型: String、Long、Integer
public final String name; //名称,没啥实际作用
public final boolean primaryKey; //是否主键
public final String columnName; //列名称,对应数据库的表的真实column名
public boolean mIsUnique; //是否唯一
public boolean mIsNotNull; //是否非空
Index
新增了Index,允许开发者定义Index就能增加索引
public class Index {
public String mType; //索引类型,如UNIQUE
public String mName;
public DaoProperty[] mColumnList;
public Index(String aType, String aName, DaoProperty... aColumnList) {
mType = aType;
mName = aName;
mColumnList = aColumnList;
}
public Index(String aName, DaoProperty... aColumnList) {
this("", aName, aColumnList);
}
}
AbstractDaoManager
我们引入了AbstractDaoManager,它管理着DaoMaster所能管理的以及不能管理的工作。它和DaoMaster最主要的区别在于数据库自动创建及升级
数据库自动创建有以下功能:
- 根据所定义的Property自动创建Table
- 根据所定义的Index自动创建
数据库自动升级有以下功能:
- 根据所定义的Property进行升级。开发者无需关心表中column的新增,每次数据库升级时,AbstractDaoManager会根据table新增的column自动创建
- 根据所定义的Index进行升级。同上
关键代码如下:
@Override
public void onCreate(Database db) {
try{
db.beginTransaction();
for (Class daoCls : sDaoClasses) {
DaoConfig daoConfig = getDaoConfig(db, daoCls);
//创建table
db.execSQL(SqlUtils.createTableSql(daoConfig));
//创建索引
SqlUtils.executeUpdateTableIndexSql(db ,daoCls, daoConfig);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
try {
db.beginTransaction();
for (Class daoCls : sDaoClasses) {
DaoConfig daoConfig = getDaoConfig(db, daoCls);
//更新前准备,由业务方去做想做的事情
onBeforeUpgradeTable(db, oldVersion, newVersion, daoCls , daoConfig);
//更新表
db.execSQL(SqlUtils.createTableSql(daoConfig));
//更新索引
try {
SqlUtils.executeUpdateTableIndexSql(db, daoCls, daoConfig);
} catch (Exception ex) {
onUpgradeIndexError(db, oldVersion, newVersion, daoCls , daoConfig);
}
//更新属性
DaoProperty[] properties = new DaoProperty[daoConfig.properties.length];
for (int i = 0; i < daoConfig.properties.length; i++) {
properties[i] = (DaoProperty) daoConfig.properties[i];
}
for (DaoProperty property : properties) {
if (!SqlUtils.checkPropertyExist(db, daoConfig.tablename, property)) {
db.execSQL(SqlUtils.addDaoPropertySql(daoConfig.tablename, property));
}
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
UpdateBuilder
增加BaseDatabaseDao,里面扩展了UpdateBuilder,支持数据库的属性更新
关键代码如下:
public class UpdateBuilder<T> {
public UpdateBuilder<T> set(DaoProperty aPropertie, Object value) {
mProperties.add(aPropertie);
mValues.add(value);
return this;
}
public UpdateBuilder<T> where(WhereCondition cond, WhereCondition... condMore) {
}
public UpdateBuilder<T> whereOr(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore) {
}
public WhereCondition or(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore) {
}
public WhereCondition and(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore) {
}
public int build() {
}
}
以上就是对GreenDao进行的扩展改造,让greenDao支持更加丰富的功能,使用起来更加的舒服。GreenDao的DaoGenerator,说实话,首次使用价值比较高,非首次也基本没什么价值了。
TODO
- 不允许主线程访问数据库
- and so on