GreenDao在Android项目中的实践总结
Posted Danny_姜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GreenDao在Android项目中的实践总结相关的知识,希望对你有一定的参考价值。
文章目录:
1 GreenDao 基本使用
2 GreenDao 多表之间的关联
3 GreenDao 保存List 类型数据
4 GreenDao 版本升级
基本使用
1 引入GreenDao
在project的build.gradle中引入GreenDao插件
buildscript
repositories
mavenCentral()
dependencies
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
然后在app的build.gradle中添加依赖
implementation 'org.greenrobot:greendao:3.2.2'
2 配置GreenDao
同样是在app的build.gradle中,添加如下配置
apply plugin: 'org.greenrobot.greendao'
greendao
schemaVersion 8
daoPackage 'your_package.greendao.gen'
targetGenDir 'src/main/java'
解释说明:
schemaVersion 指定数据库schema版本号,数据库的迁移等操作会用到
daoPackage 指定数据库dao的包名,默认是和Entity所在的包
targetGenDir 表示生成数据库包的目标路径
3 建立数据库实体类
@Entity
public class User
@Id
private Long id;
@Property(nameInDb = "USERNAME")
private String username;
@Property(nameInDb = "NICKNAME")
private String nickname;
解释说明:
@Entity 表示这个实体类一会会在数据库中生成对应的 数据库表
@Id 表示该字段是id
@Property 则表示该属性将作为表的一个字段,其中nameInDb看名字就知道这个属性在数据库中对应的字段名称(列)
GreenDao每遍历到一个Entity注解时,都会为之创建一个相应的表格table,上述User的表格格式如下图所示:
当实体类创建成功之后, 使用如下命令编译整个项目:
./gradlew clean greendao
GreenDao会根据此实体类,自动生成XXXDao类,并保存在build.gradle中配置的daoPackage路径下,结果如下图所示:
图中红框处,GreenDao会默认生成DaoMaster和DaoSession两个类文件,通过这两个类来操作项目中创建的各个 数据库表 。
此外,为了方便数据库的操作,GreenDao默认还为Entity中的属性Properties设置了setter和getter方法,比如经过编译之后,Use.java中多了几个set和get方法,如下:
@Entity
public class User
@Id
private Long id;
@Property(nameInDb = "USERNAME")
private String username;
@Property(nameInDb = "NICKNAME")
private String nickname;
@Generated(hash = 523935516)
public User(Long id, String username, String nickname)
this.id = id;
this.username = username;
this.nickname = nickname;
@Generated(hash = 586692638)
public User()
public Long getId()
return this.id;
public void setId(Long id)
this.id = id;
public String getUsername()
return this.username;
public void setUsername(String username)
this.username = username;
public String getNickname()
return this.nickname;
public void setNickname(String nickname)
this.nickname = nickname;
4 数据库初始化
通过DevOpenHelper类对数据库进行初始化操作,DevOpenHelper有点类似于android SDK中自带的SQLiteOpenHelper。
// 首先获取一个DevOpenHelper对象
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "db_demo.db");
// 通过Helper类获取DaoMaster类
DaoMaster daoMaster = new DaoMaster(helper.getWritableDb());
// 通过DaoMaster获取DaoSession类,此类是操作数据库的关键
DaoSesson daoSession = daoMaster.newSession();
在构建DevOpenHelper时,需要指定创建的数据库名称。比如上述代码中,我创建了一个名为 db_demo.db 的数据库。
5 操作数据库
首先通过DaoSession获取响应的XXXDao对象,比如我之前创建的Entity实体类是User.java,编译之后GreenDao会自动生成UserDao.java类,因此我们需要通过DaoSession获取UserDao对象,并进行数据库增删改查操作,如下:
// 获取 UserDao 对象 -> 也就是 user 表格的引用
UserDao userDao = daoSession.getUserDao();
// 向 user 表格中插入数据
User user = new User();
user.setUsername("Danny");
user.setNickname("星哥");
userDao.insert(user);
执行上述代码,然后在 data/data/packageName目录下多了一个databases目录,在databases目录中有一个 db_demo.db 的数据库文件:
generic_x86:/data/data/com.danny.greendaopractise/databases # ls
db_demo.db db_demo.db-journal
通过sqlite3 命令可以连接此数据库,并查看内部表格中的数据:
generic_x86:/data/data/com.danny.greendaopractise/databases # sqlite3 db_demo.db
sqlite> select * from USER;
1|Danny|星哥
sqlite>
可以看出,成功向USER表格中创建了1条记录。除此之外,在代码中也可以通过以下方式查询表格中的内容:
List<User> users = userDao.queryBuilder().list();
GreenDao保存List类型数据
1 GreenDao默认不支持List插入
实际项目中,Entity实体类中可能会包含List类型的数据。比如在User中添加如下地址addresses字段:
其它代码不变,重新执行之前的代码,会发现代码如法经过编译,报错日志如下:
说明GreenDao默认是不支持以List的格式向数据库中插入数据的,在GreenDao自动生成的UserDao中有如下代码:
可以看出,GreenDao会将Entity类中的ID以及相关属性(Properties)设置到SQLiteStatement中,最终通过SQLiteStatement执行sql语句。
但是SQLiteStatement只能bind基本类型和String类型数据,如下所示:
2 将List<String>数据进行转化
如果要解决List数据插入问题,可以转换一下思路:遍历List数据,然后将所有的String对象都append到一个StringBuilder中,最终将StringBuild转化为String类型然后保存在数据库中即可。
事实上,GreenDao已经为我们考虑到了这种情况,因此才有了 PropertyConverter 这个接口。
在PropertyConverter接口中,有两个需要实现的抽象方法:
我们只需要实现此接口,并实现这两个抽象方法即可。具体如下:
需要传入泛型,分别是需要进行转换的List数据类型,以及最终被转化的目标数据类型。比如上述代码中,我们需要将User中的Listaddresses转化为String类型。
定义好StringConverter之后,接下来需要通过注解将StringConverter指定到需要进行转换的字段中,比如User.java 中的 addresses 字段:
通过注解 @Convert 指定addresses字段的转化工具类。
此时可以成功编译项目,再次查看UserDao中的bindValue方法,发现有如下改变:
如红框中所示,GreenDao解析@Convert注解时,会使用指定的Converter将List数据转化为String类型,并绑定到SQLiteStatement中进行数据库操作。
3 验证结果
使用如下代码,再次向数据库 db_demo.db 中插入一条数据
执行完之后,再次查看数据库中内容如下:
注意:执行之前,需要将之前的APK卸载,因为之前的数据库结构中并不存在addresses列,会造成程序崩溃。
实际开发中,对于比较复杂的List集合,可以考虑使用Gson来执行String和Bean之间的切换。
GreenDao多表之间关联
但是在实际开发中经常会遇到List的泛型并不是String类型的,而是另外一种自定义的Entity类型。比如新建一个Order.java 代表用户的某一个订单详情:
然后在User类中添加一个订单的集合,如下所示:
这种情况就需要将Order也定义为一个表格,并将它与User表格建立关联。具体如下:
然后在User中建立一对多的关系,如下:
红框中的 @ToMany 表示一个User可以对应订单Order表格中的多条记录,这与显示情况也是一致的,我们平时在购物平台上买东西,或者外卖平台上点外卖都可以多次下单,但是多有订单都指向同一个用户。这就是 "一对多" 的关系。
编译之后,可以看到在User中又多了对Order集合的操作
上面的操作是GreenDao自动生成的对Order集合的访问和操作,可以看出只包含了查找和重置所有订单的操作。
但是实际情况中,用户可以对某一个订单进行多次修改,因此后续需要程序开发人员在User中添加多种对订单的处理以及优化。
GreenDao 版本升级
上文中说过如果数据库的结构有改变,需要将之前的APK下载并重新安装。否则会因为数据库无法查找到字段而导致程序崩溃。但是在实际情况中,确实有需要做数据库升级的情况发生。比如后端数据结构一开始没有设计好,当生存环境已经有用户安装了APK时,后续就需要通过数据库升级来更新数据库的结构。
比如进行User表格的升级
GreenDao为我们提供了数据库升级的入口是在DaoMaster.OpenHelper 中。OpenHelper实际是继承自Android SDK中的DatabaseOpenHelper,当build.gradle中的GreenDao schemaVersion发送改变时(升级),会触发onUpgrade方法,进行数据库升级操作。
通常情况下,在onUpgrade方法中,我们需要做数据迁移工作。主要是将数据库现有表格的数据迁移到新的表格中,主要包含以下几步:
创建临时表,复制原来的数据库到临时表中
复制原来的数据库到临时表中
数据迁移:将临时表中的数据复制到新表中,最后将临时表删除
1 创建临时表
红框中为构建建表Sql语句,最后通过db.execSQL来执行此语句建临时表。
2 删除之前的原表并建立新表
删表和建表的操作很简单,只需要执行XXXDao的相应方法即可。以UserDao为例:
3 数据迁移
这一步比较关键,主要分2步完成
将临时表中的数据复制到新表中
删除临时表
完整代码如下:
解释说明:
图中1处将临时表中的数据插入到新建表格中
图中2处构建删表语句,并执行删除临时表
注意:
在实际项目中,不一定每次数据库版本升级都需要做数据迁移的操作。毕竟这是一个比较耗时耗力也容易出错的操作。因此需要根据版本号来判读当前设备中的数据库是否需要做迁移。
即使是需要做迁移,也并不是每一个表格都需要做迁移操作。比如上面的案例中只需要将User表格中的数据做迁移即可,最大程度的减少数据库表格的重建操作。
往期精选
Android源码系列
2 RecyclerView.ItemAnimator实现动画效果
3 RecyclerView.ItemAnimator源码解析
JVM深入理解系列
如果你喜欢本文
长按二维码关注
以上是关于GreenDao在Android项目中的实践总结的主要内容,如果未能解决你的问题,请参考以下文章
android greendao3.0 多表关联关系讲解(转)
Android GreenDao 在组件化项目中的一个问题 - 2018年7月5日21:15:14