GreenDao 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案。(greenDAO is a light & fast ORM solution that maps objects to SQLite databases), 而关于 ORM (Object Relation Mapping - 对象关系映射)的概念,可参见 Wikipedia。
GreenDAO整个运行的逻辑是通过配置其提供的JavaSE代码,自动在一个文件夹下生成需要Bean、DAO、DaoMaster、DaoSession;然后在Android代码中通过自动生成的DaoSession来操作数据库,具体方法如下:
打开build.gradle,引入sourceSets
//java-gen为greendao代码生成目录
sourceSets {
main {
java.srcDirs = ['src/main/java', 'src/main/java-gen']
}
}
这句话的意思是把java-gen文件夹下的java文件也归入srcDir中,主要是因为GreenDAO的逻辑是通过其提供的一套Java SE代码配置后自动在java-gen文件夹下生成对应的*DAO.java、DaoMaster.java、DaoSession.java文件。在Android代码中通过调用这几个类来操作数据库。
compile 'de.greenrobot:greendao:1.3.7'
通过 File -> New -> New Module -> Java Library -> 填写相应的包名与类名 -> Finish.
配置 green_dao_lib工程的 build.gradle,添加 dependencies.
compile 'de.greenrobot:greendao-generator:1.3.1'
public class CodeGenerator {
public static void main(String[] args) throws Exception {
// 1.创建了一个用于添加实体(Entity)的模式(Schema)对象
//两个参数分别代表:数据库版本号与自动生成代码的包路径。
//每次修改都要对版本号进行升级
Schema schema = new Schema(5, "com.xiaozai.greendao");
//2.一旦你拥有了一个 Schema 对象后,你便可以使用它添加实体(Entities)了。
addVideoPlayHistory(schema);//播放记录表
//3.最后我们将使用 DAOGenerator 类的 generateAll() 方法自动生成代码,此处你需要根据自己的情况更改输出目录(既之前创建的 java-gen)。
//其实,输出目录的路径可以在 build.gradle 中设置,def outputDir = "..xz/src/main/java-gen"
new DaoGenerator().generateAll(schema, "xz/src/main/java-gen");//自动生成代码存放路径
}
/**
* 视频播放记录表
*
* @param schema
*/
private static void addVideoPlayHistory(Schema schema) {
//一个实体(类)就关联到数据库中的一张表
Entity table = schema.addEntity("VideoPlayHistory");//表名
// greenDAO 会自动根据实体类的属性值来创建表字段,并赋予默认值
// 接下来你便可以设置表中的字段:
table.addStringProperty("album_id").primaryKey();//专辑ID
table.addStringProperty("video_id");//视频ID
table.addStringProperty("video_play_url").notNull();//视频播放地址
table.addLongProperty("recent_play_date");//最后一次播放时间
table.addLongProperty("video_time");//视频时长
table.addIntProperty("video_play_position");//上一次播放的位置
table.addStringProperty("video_img");//视频缩略图
table.addStringProperty("video_name");//视频名称
table.addStringProperty("has_next");//是否还有下一集
table.addStringProperty("current_set");//当前是第几集
table.addStringProperty("total_set");//专辑总共有多少集
}
}
执行 generator 工程,如一切正常,在主工程「java-gen」下会自动生成DaoMaster、DaoSession、VideoPlayHistory、VideoPlayHistoryDao等,分别是实体类和实体类的对应的Dao类成对出现。
private SQLiteDatabase db;
private DaoMaster daoMaster;
private DaoSession daoSession;
private void setupDatabase() {
if (daoSession == null) {
// 通过 DaoMaster 的内部类 DevOpenHelper,你可以得到一个便利的 SQLiteOpenHelper 对象。
// 可能你已经注意到了,你并不需要去编写「CREATE TABLE」这样的 SQL 语句,因为 greenDAO 已经帮你做了。
// 注意:默认的 DaoMaster.DevOpenHelper 会在数据库升级时,删除所有的表,意味着这将导致数据的丢失。
// 所以,在正式的项目中,你还应该做一层封装,来实现数据库的安全升级。
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "xiaozai_db.db", null);
db = helper.getWritableDatabase();
// 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。
daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
}
}
public DaoSession getDaoSession() {
return daoSession;
}
这run执行之后就会在app的文件夹下生成xiaozai_db.db了
/**
* 视频记录相关DAO
*/
public class VideoDao {
private static VideoDao instance = new VideoDao();
private VideoDao() {
}
private VideoPlayHistoryDao mDao;
public static VideoDao getInstance() {
if (instance.mDao == null) {
instance.mDao = RndApplication.getInstance().getDaoSession().getVideoPlayHistoryDao();
}
return instance;
}
public void saveVideoPlay(VideoPlayHistory vph) {
mDao.insertOrReplace(vph);
}
/**
* 按最近播放时间排序
*
* @return
*/
public List getAll() {
QueryBuilder qb = mDao.queryBuilder();
qb.orderDesc(VideoPlayHistoryDao.Properties.Recent_play_date);
return qb.list();
}
public VideoPlayHistory findVideoById(String videoId) {
QueryBuilder qb = mDao.queryBuilder();
qb.where(VideoPlayHistoryDao.Properties.Video_id.eq(videoId));
List list = qb.list();
if (list != null && list.size() > 0) {
return list.get(0);
}
return null;
}
public VideoPlayHistory findVideoByAlbumid(String albumid) {
return mDao.load(albumid);
}
public void delete(String albumid) {
mDao.deleteByKey(albumid);
}
public void deleteByVideoId(String videoId) {
mDao.delete(findVideoById(videoId));
}
}
从5中得知,默认的 DaoMaster.DevOpenHelper 会在数据库升级时,删除所有的表,意味着这将导致数据的丢失。所以,在正式的项目中,你还应该做一层封装,来实现数据库的安全升级。具体的封装,可以看一下这篇博客在AndoridStudio中引入GreenDAO.
我在数据库升级的时候并没有封装 DaoMaster.DevOpenHelper ,是这样做的(供参考):
(1) 将java工程green_dao_lib添加为依赖
(2.)修改版本号,需要新创建表则从新建表,新加字段则新加字段
(3).重新run该java工程,重新生成DaoMaster DaoSession等文件,此时数据库并不会覆盖原来的数据库,而是会更新;
(4).打包时遇到一点问题,因此我将该java工程去掉依赖,打包时不含该java工程
参考资料
ORM 框架之 greenDAO 使用心得