之前在开发过程中,数据库基本上会使用Litepal或者SQlite自己写,最近换新环境,公司原先使用的数据库就是GreenDao,在各种情况的作用下,准备了解下GreenDao,顺便写一篇文章记录下GreenDao的基本使用!如果你是Android开发者,你在开发路上遇到任何问题,欢迎来我的公众号给我留言,咱们一起讨论,加入的Android开发讨论小组,一起进步!文章转载请注明出处。
本文主要从如下几个方面进行讲解
- 存储的数据库结构
- GreenDao的优缺点
- GreenDao的使用配置
- 使用GreenDao实现数据的增删改查
- GreenDao的注解使用
- GreenDao的关系处理
- GreenDao的升级
- GreenDao数据库加密
- 项目地址AserbaosAndroid
- 总结
- 参考博客
咱们先看一波最终的效果图:文章最后有项目地址;
学习数据库之前,我们先得设计自己的数据库,不多废话,下面是我此次学习的数据库结构,后面所有的数据请参考这个图进行学习:
简单的GreenDao的介绍,嫌麻烦的可以直接跳到GreenDao使用开始看。
GreenDAO是一个开源的Android ORM(“对象/关系映射”),通过ORM(称为“对象/关系映射”),在我们数据库开发过程中节省了开发时间!
- GreenDao:适用于您的SQLite数据库的Android ORM
- GreenDao的github地址
- GreenDao的Google讨论区
- GreenDao 加密SQLCipher for Android官方说明地址
- GreenDao使用文档
通过GreenDao,我们可以更快速的操作数据库,我们可以使用简单的面相对象的API来存储,更新,删除和查询Java对象。
- 高性能,下面是官方给出的关于GreenDao,OrmLite和ActiveAndroid三种ORM解决方案的数据统计图:
- 易于使用的强大API,涵盖关系和连接;
- 最小的内存消耗;
- 小库大小(<100KB)以保持较低的构建时间并避免65k方法限制;
- 数据库加密:greenDAO支持SQLCipher,以确保用户的数据安全;
GreenDao的核心类有三个:分别是DaoMaster,DaoSession,XXXDao,这三个类都会自动创建,无需自己编写创建!
- DaoMaster::DaoMaster保存数据库对象(SQLiteDatabase)并管理特定模式的DAO类(而不是对象)。它有静态方法来创建表或删除它们。它的内部类OpenHelper和DevOpenHelper是SQLiteOpenHelper实现,它们在SQLite数据库中创建模式。
- DaoSession:管理特定模式的所有可用DAO对象,您可以使用其中一个getter方法获取该对象。DaoSession还提供了一些通用的持久性方法,如实体的插入,加载,更新,刷新和删除。
- XXXDao:数据访问对象(DAO)持久存在并查询实体。对于每个实体,greenDAO生成DAO。它具有比DaoSession更多的持久性方法,例如:count,loadAll和insertInTx。
- Entities :可持久化对象。通常, 实体对象代表一个数据库行使用标准 Java 属性(如一个POJO 或 JavaBean )。
要在Android项目中使用GreenDao,您需要添加GreenDao Gradle插件并添加GreenDao库:
- 导入插件
- 配置相关依赖
- 配置数据库相关信息
配置完成,在Android Studio中使用Build> Make Project,重写build项目,GreenDao集成完成!
使用GreenDao存储数据只需要在存储数据类前面声明@Entity注解就让GreenDao为其生成必要的代码:
我们可以在Application中维持一个全局的会话。我们在Applicaiton进行数据库的初始化操作:
初始化完成之后重新rebuild一下项目会发现在设置的targetGenDir的目录生成三个类文件,这个是GreenDao自动生成的!说明数据库已经连接好了,咱们接下来只需要进行数据库的增删改查操作就行了。Let's Go!
insert() 插入数据
insertOrReplace()数据存在则替换,数据不存在则插入
删除有两种方式:delete()和deleteAll();分别表示删除单个和删除所有。
通过update来进行修改:
查询的方法有:
- loadAll():查询所有数据。
- queryRaw():根据条件查询。
- queryBuilder() : 方便查询的创建,后面详细讲解。
编写SQL可能很困难并且容易出现错误,这些错误仅在运行时才会被注意到。该QueryBuilder的类可以让你建立你的实体,而不SQL自定义查询,并有助于在编译时已检测错误。
我们先讲下QueryBuilder的常见方法:
- where(WhereCondition cond, WhereCondition... condMore): 查询条件,参数为查询的条件!
- or(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore): 嵌套条件或者,用法同or。
- and(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore): 嵌套条件且,用法同and。
- join(Property sourceProperty, Class destinationEntityClass):多表查询,后面会讲。 输出结果有四种方式,选择其中一种最适合的即可,list()返回值是List,而其他三种返回值均实现Closeable,需要注意的不使用数据时游标的关闭操作:
- list ()所有实体都加载到内存中。结果通常是一个没有魔法的 ArrayList。最容易使用。
- listLazy ()实体按需加载到内存中。首次访问列表中的元素后,将加载并缓存该元素以供将来使用。必须关闭。
- listLazyUncached ()实体的“虚拟”列表:对列表元素的任何访问都会导致从数据库加载其数据。必须关闭。
- listIterator ()让我们通过按需加载数据(懒惰)来迭代结果。数据未缓存。必须关闭。
- orderAsc() 按某个属性升序排;
- orderDesc() 按某个属性降序排;
GreenDao中SQL语句的缩写,我们也了解下,源码在Property中,使用的时候可以自己点进去查询即可:
- eq():"equal ('=?')" 等于;
- notEq() :"not equal ('<>?')" 不等于;
- like():" LIKE ?" 值等于;
- between():" BETWEEN ? AND ?" 取中间范围;
- in():" IN (" in命令;
- notIn():" NOT IN (" not in 命令;
- gt():">?" 大于;
- lt():"<? " 小于;
- ge():">=?" 大于等于;
- le():"<=? " 小于等于;
- isNull():" IS NULL" 为空;
- isNotNull():" IS NOT NULL" 不为空;
查询当前Student表的所有的数据:
查询Name为“一”的所有Student:
通过原始的SQL查询语句进行查询!其实上面有提到QueryBuilder的目的就是方便快捷的编写SQL查询语句,避免我们自己在编写过程中出错!简单介绍下通过QueryBuilder编写数据库,方式方法如下 :
查询Id大于5小于10,且Name值为"一"的数据:
取10条Id大于1的数据,且偏移2条
使用QueryBuilder构建查询后,可以重用 Query对象以便稍后执行查询。这比始终创建新的Query对象更有效。如果查询参数没有更改,您可以再次调用list / unique方法。可以通过setParameter方法来修改条件参数值:
如果在多个线程中使用查询,则必须调用 forCurrentThread ()以获取当前线程的Query实例。Query的对象实例绑定到构建查询的拥有线程。
这使您可以安全地在Query对象上设置参数,而其他线程不会干扰。如果其他线程尝试在查询上设置参数或执行绑定到另一个线程的查询,则会抛出异常。像这样,您不需要同步语句。实际上,您应该避免锁定,因为如果并发事务使用相同的Query对象,这可能会导致死锁。
每次调用forCurrentThread ()时, 参数都会在使用其构建器构建查询时设置为初始参数。
使用QueryBuilder进行批量删除操作,不会删除单个实体,但会删除符合某些条件的所有实体。要执行批量删除,请创建QueryBuilder,调用其 buildDelete ()方法,然后执行返回的 DeleteQuery。
例子:删除数据库中id大于5的所有其他数据
从GreenDao 3 使用注解来定义模型和实体,前面也讲过,通过注解的使用可以快速构建数据库表,包括设置主键,自增,值是否唯一等等等……
下面我们来看下注解的简单使用:
@Entity是GreenDao必不可少的注解,只有在实体类中使用了@Entity注解GreenDao才会创建对应的表。当然我们也可以使用@Entity配置一些细节:
- schema:如果你有多个架构,你可以告诉GreenDao当前属于哪个架构。
- active:标记一个实体处于活跃状态,活动实体有更新、删除和刷新方法。
- nameInDb:在数据中使用的别名,默认使用的是实体的类名。
- indexes:标记如果DAO应该创建数据库表(默认为true),如果您有多个实体映射到一个表,或者表的创建是在greenDAO之外进行的,那么将其设置为false。
- createInDb:标记创建数据库表。
- generateGettersSetters:如果缺少,是否应生成属性的getter和setter方法。
@Id @Id注解选择 long / Long属性作为实体ID。在数据库方面,它是主键。参数autoincrement = true 表示自增,id不给赋值或者为赋值为null即可(这里需要注意,如果要实现自增,id必须是Long,为long不行!)。
@Property 允许您定义属性映射到的非默认列名。如果不存在,GreenDAO将以SQL-ish方式使用字段名称(大写,下划线而不是camel情况,例如 name将成为 NAME)。注意:您当前只能使用内联常量来指定列名。
@NotNull :设置数据库表当前列不能为空 。
@Transient :添加次标记之后不会生成数据库表的列。标记要从持久性中排除的属性。将它们用于临时状态等。或者,您也可以使用Java中的transient关键字。
- @Index:使用@Index作为一个属性来创建一个索引,通过name设置索引别名,也可以通过unique给索引添加约束。
- @Unique:向索引添加UNIQUE约束,强制所有值都是唯一的。
注意: 上面这种情况,约定name为唯一值,向数据库中通过insert方法继续添加已存在的name数据,会抛异常:
若使用insertOrReplace()方法添加数据,当前数据库中不会有重复的数据,但是重复的这条数据的id会被修改!若项目中有用到id字段进行排序的话,这一点需要特别注意。
关系型注解GreenDao中主要就两个:
- @ToOne:定义与另一个实体(一个实体对象)的关系
- @ToMany:定义与多个实体对象的关系 至于如何使用,我们马上就讲。
平常项目中,我们经常会使用到多表关联,如文章开头所说的数据库表结构设置的那样!接下来我们来讲如何通过GreenDao实现多表关联。
一个学生对应一个身份证号: 做法:
- 我们在Student中设置一个注解@ToOne(joinProperty = "name")
- 在创建Student的时候,将对应的数据传递给IdCard; 代码部分:
学生Student代码:
身份证IdCard代码:
insert一组数据:
ok,数据可以了!现在数据库表插入完成了。
一个人拥有多个信用卡 做法:
- 在我们在Student中设置@ToMany(referencedJoinProperty = "studentId");
- 我们在CreditCard中设置编写对应的id主键;
Student的代码:
CreditCard的代码:
添加数据代码:
一个学生有多个老师,老师有多个学生。 做法:
- 我们需要创建一个学生老师管理器(StudentAndTeacherBean),用来对应学生和老师的ID;
- 我们需要在学生对象中,添加注解:
@ToMany @JoinEntity(entity = StudentAndTeacherBean.class,sourceProperty = "studentId",targetProperty = "teacherId") List teacherList;
- 我们需要在老师对象中,添加注解:@ToMany
@JoinEntity(entity = StudentAndTeacherBean.class,sourceProperty = "teacherId",targetProperty = "studentId") List studentList;
StudentAndTeacherBean代码:
Student 代码:
Teacher代码:
数据添加:
好了,成功;
GreenDao的OpenHelper下有个 onUpgrade(Database db, int oldVersion, int newVersion)方法,当设置的数据库版本改变时,在数据库初始化的时候就会回调到这个方法,我们可以通过继承OpenHelper重写onUpgrade方法来实现数据库更新操作:
GreenDao的升级思路:
- 创建临时表TMP_,复制原来的数据库到临时表中;
- 删除之前的原表;
- 创建新表;
- 将临时表中的数据复制到新表中,最后将TMP_表删除掉;
ok,思路就是这样, 总共两个类: 一个MyDaoMaster(OpenHelper继承类),一个MigrationHelper(数据库操作类) 下面是代码编写:
修改Application中的DaoMaster的创建:
MyDaoMaster代码:
MigrationHelper 代码:
开发中对于存储于数据库中的敏感数据,我们可以通过对数据库加密来进行保护。GreenDao可以通过SQLCipher来进行加密处理。下面我们简单讲解下加密过程:
步骤:
- 导入加密库文件:
- 修改DaoSession的生成方式:
当前文章所有代码在AserbaosAndroid/app/src/main/java/com/aserbao/aserbaosandroid/functions/database/greenDao/relation目录下;(不过就我这脾气,可能在今后整理代码的过程中会修改!不过请放心,修改后会在github上进行说明的)
AserbaosAndroid aserbao的个人Android总结项目,希望这个项目能成为最全面的Android开发学习项目,这是个美好的愿景,项目中还有很多未涉及到的地方,有很多没有讲到的点,希望看到这个项目的朋友,如果你在开发中遇到什么问题,在这个项目中没有找到对应的解决办法,希望你能够提出来,给我留言或者在项目github地址提issues,我有时间就会更新项目没有涉及到的部分!项目会一直维护下去。当然,我希望是Aserbao'sAndroid 能为所有Android开发者提供到帮助!也期望更多Android开发者能参与进来,只要你熟悉Android某一块,都可以将你的代码pull上分支!
这篇文章写到这里,零零碎碎花了差不多两周时间,从十月八号开始到今天正式准备发布,也算是对GreenDao数据库的进一步认识!如文章开头所说,我Android开发之初,使用的是自己编写SQLite来实现数据库存储,到后来使用第三方存储LitePal,最近,项目早期就使用了GreenDao,所以就又学习了一番GreenDao。对于开发者来说,我觉得无论是这三种中的哪一种,其实只要掌握一种我觉得就足够了!当然如果你有时间,可以多学习几种,多学无害嘛!最后,一如既往的说一下:如果你是Android开发者,你在开发路上遇到任何问题,欢迎来我的公众号给我留言,咱们一起讨论,加入Android开发讨论小组,一起进步!文章转载请注明出处。
Android ORM 框架:GreenDao 使用详解 Android数据存储之GreenDao 3.0 详解 拆轮子系列之GreenDao框架原理分析
- CreditCard中不能只使用一个useId来做关联,因为我这里Teacher和Student都和CreditCard是一对多关系,所以我们需要建两个对应关系字段。为了分辨添加了studentId和teacherId。
- Student中的@ToMany(referencedJoinProperty =“id”)这个id对应的是CreditCard中的studentId,不是自增Id。(问题由@山豆几_提出,感谢) 修改后的代码应该是:
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/2102.html