背景:

最近在搞一个设备权限同步的功能:设备是一个Android设备,其中权限同步是后端将权限的内容通过mqtt消息通知到设备端,然后设备端再发送Http请求到后端请求数据。
那么问题来了,权限的内容肯定是要存储在设备端的,Android中是自带sqlite数据库,那么相对就简单一点了。但是原生的sqlite操作是比较复杂的,所以我想找找看有没有一些第三方的库。

GreenDao

greenDAO是一款开源的面向 Android 的轻便、快捷的 ORM 框架,将 Java 对象映射到SQLite数据库中,我们操作数据库的时候,不再需要编写复杂的 SQL语句, 在性能方面,greenDAO针对 Android 进行了高度优化, 最小的内存开销 、依赖体积小 同时还是支持数据库加密

简单点说:GreenDao就是一款ORM框架。ORM大家都应该很熟悉吧?就是和Hibernate差不多:把数据库的字段和实体类 做了映射关系。简化sql。

前期准备

1. 导入相关依赖

  1. 工程的 build.gradle
buildscript {    repositories {        google()        jcenter()            }    dependencies {        classpath 'com.android.tools.build:gradle:3.5.2'        // 添加插件 更好支持GreenDao        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'         // NOTE: Do not place your application dependencies here; they belong        // in the individual module build.gradle files    }}
  1. 在app目录下的build.gradle配置
apply plugin: 'org.greenrobot.greendao'greendao {    //如果扩列了,或者修改表结构之类的,记得schemaVersion+1    schemaVersion 1    //设置DaoMaster、DaoSession、Dao包名,也就是要放置这些类的包的全路径。(此路径下自动生成一些dao文件。)    daoPackage 'com.gh.greendaodemo.gen'    //设置DaoMaster、DaoSession、Dao目    targetGenDir 'src/main/java'}dependencies {    implementation fileTree(dir: 'libs', include: ['*.jar'])    implementation 'androidx.appcompat:appcompat:1.1.0'    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'    testImplementation 'junit:junit:4.12'    androidTestImplementation 'androidx.test.ext:junit:1.1.1'    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'    // 添加库    implementation 'org.greenrobot:greendao:3.2.2'    implementation 'com.google.code.gson:gson:2.8.5'}

2. 创建表结构

greenDao中创建表的过程其实就是创建实体类过程
greenDao通过注解的方式创建表

package com.gh.greendaodemo.table;import org.greenrobot.greendao.annotation.Entity;import org.greenrobot.greendao.annotation.Id;import org.greenrobot.greendao.annotation.Index;import org.greenrobot.greendao.annotation.Property;import org.greenrobot.greendao.annotation.Transient;import org.greenrobot.greendao.annotation.Unique;import java.util.List;import org.greenrobot.greendao.annotation.Generated;/** * @author Created by cj on 2020/3/25. * @description 说明 一个creationDate的属性,会变成数据库中的列的名字会是CREATION_DATE。 * Email 1206067690@qq.com */@Entity(nameInDb = "user_info")public class UserInfoTable {    /**     * 主键 Long型,可以通过@Id(autoincrement = true)设置自增长。     * 通过这个注解标记的字段必须是Long,数据库中表示它就是主键,并且默认是自增的。     */    @Id(autoincrement = true)    private Long id;    /**     * Unique 属性给数据库的列添加了一个唯一性限制。注意,SQLite也会隐式地为它创建一个索引。     * Property :属性指定数据库的字段名称。默认是驼峰转成大写的下划线隔开的名称,比如:UserAge 转成 USER_AGE     *///    @Unique    @Property(nameInDb = "user_number")    private String userNumber;    @Property(nameInDb = "user_name")    private String userName;    @Property(nameInDb = "user_age")    private String userAge;    @Property(nameInDb = "level")    private String level;    @Transient    private List<TeacherInfoTable> teacherInfoTableList;}

这边注解的功能我都注释了。大家可以看下。
这里需要注意的是,id的类型必须要是Long类型。
注意不是long是Long(下面会给大家说明)

3. Make Project

build -> Make Project
或者 ctrl+F9;

GreenDao基本操作

经过前面的步骤,大家可以查看下之前在app中的build.gradle中配置的DaoMaster路径,看看有没有生成对应的文件。类似于:
Android系列之GreenDao基本使用(增、删、改、查)(一)_第1张图片
一个table 对应一个Dao,DaoMaster和DaoSession都是基础的类。

1. 创建数据库

先来代码:

 // 通过 DaoMaster 的内部类 DevOpenHelper,你可以得到一个便利的 SQLiteOpenHelper 对象。        // 可能你已经注意到了,你并不需要去编写「CREATE TABLE」这样的 SQL 语句,因为 greenDAO 已经帮你做了。        // 注意:默认的 DaoMaster.DevOpenHelper 会在数据库升级时,删除所有的表,意味着这将导致数据的丢失。        // 所以,在正式的项目中,你还应该做一层封装,来实现数据库的安全升级。        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "test.db");        db = helper.getWritableDatabase();        mDaoMaster = new DaoMaster(db);        mDaoSession = mDaoMaster.newSession();

DevOpenHelper 有两个参数:
第一个是 Conext 也就是上下文。
第二个是sql的文件名称:地址默认是data/data/应用包名/files 下面
我们可以看到除了第一步和SQLiteOpenHelper 不一样。下面都是一样的,通过getWritableDatabase获取SQLiteDatabase实例,然后赋值到DaoSession当中去,后续通过DaoSession就可以直接使用了。

2. 增、删、改、查

说明: 首先GreenDao的增删改查都很简单,我这里就不展开说明了,基本都是一个方法搞定的事儿,毕竟ORM就是方便。

1. 最简单的增删改查

mDaoSession.getUserInfoTableDao().insert(userInfoTable);mDaoSession.getUserInfoTableDao().delete(userInfoTable);mDaoSession.getUserInfoTableDao().update(userInfoTable);mDaoSession.getUserInfoTableDao().insert(userInfoTable);//查询id是1的用户mDaoSession .getUserInfoTableDao().queryBuilder().where(UserInfoTableDao.Properties.Id.eq(1)).unique();

这边着重给大家介绍下查询语句:
真实的情况相对与只查询id是1的用户这样的语句可能更要复杂一点,但是不要慌,greenDao都有对应的解决方案:
首先eq是等于的意思,那么联想一下? 不等于? 小于等于?大于等于?like?order?in?
GreenDao全都有:

操作符 实际效果
eq =
notEq <>
like LIKE
between BETWEEN … AND …
in IN (…, …, …)
notIn NOT IN (…, …, …)
gt >
lt <
ge >=
le <=
isNull IS NULL
isNotNull IS NOT NULL

在来解释下最后一个方法 unique:这是返回唯一结果或者 null
还有几个方法:

方法名 解释
unique () 返回唯一结果或者 null
list () 返回结果集
count() 返回结果数量

通过操作符的话,我们就可以操作一些相对复杂一点的sql了。
(PS:复杂不复杂这里也只有一张表,能复杂到哪儿去 =。=)

2. QueryBuilder的使用

在写查询语句的时候,我们注意到有这个一个方法queryBuilderqueryBuilder能够帮助我们创建sql,这种创建方式比较简单而且最重要的一点就是帮助我们避免自己写sql时出现的一些低级错误。
先不看源码中的方法,我们自己先想一下平常手写sql时需要的一些关键字:
whereorandjoinorderlimit。差不多就这些吧。
首先大家看下 queryBuilder的方法
Android系列之GreenDao基本使用(增、删、改、查)(一)_第2张图片
GreenDao 说:你要的我全都有
join方法的话,我下一章会单独说,这节先略。
这几个方法中都有一个共同点:参数都是WhereCondition
WhereCondition为何物呢?打开源码一看,原来是个接口类,其实现类有三个:
Android系列之GreenDao基本使用(增、删、改、查)(一)_第3张图片
于是诞生了下面三种查询写法:

 UserInfoTable infoTable = tableDao.queryBuilder().                where(UserInfoTableDao.Properties.Id.eq(userId)).unique(); UserInfoTable infoTable2 =   tableDao.queryBuilder().                where(new WhereCondition.PropertyCondition(UserInfoTableDao.Properties.Id, "=?", userId)).unique(); List<UserInfoTable> query = tableDao.queryBuilder().                where(new WhereCondition.StringCondition( "T.id =? and T.name =?", userId,"张三")).build().list();

然后我们查看eq的源码,惊奇的发现:
在这里插入图片描述
偶吼吼,不就是第二种写法么。也就是第一种和第二种都是一种写法。
下面我们重点研究下第三种写法,为什么会有这种写法呢?greenDao也是比较人性化的,你看我greenDao提供了这么多方法,都不符合你的心意,那行,你自己写条件sql总可以了吧?
所以这里就是自己写条件sql,唯一需要注意的是GreenDao对每个表都有别名的设置,别名就是 T。
截图为证
Android系列之GreenDao基本使用(增、删、改、查)(一)_第4张图片
好了,知道了这些方法之后,我们自己就可以根据需求灵活运用了。

3. 带有事务的批量操作

说明:
讲道理,GreenDao中对事务的支持也是可以的。
GreenDao对于不同的操作也提供了runInTxcallInTx方法。
runInTx和callInTx的区别就是:runInTx是异步的、callInTx是同步的,

  • 第一种情况:批量新增和批量删除以及批量修改。
mDaoSession.getUserInfoTableDao().updateInTx(infoTableList);mDaoSession.getUserInfoTableDao().deleteInTx(infoTableList);mDaoSession.getUserInfoTableDao().insertInTx(infoTableList);

这种很舒服了,三种批量都已经帮你写好了,直接用。

  • 第二种情况:针对两张表之间做事务操作:
 try {            return  mDaoSession.callInTx(new Callable<Boolean>() {                @Override                public Boolean call() throws Exception {                //具体需要的操作                    return true;                }            });             ;        } catch (Exception e) {            return false;        }

runInTx方法是没有返回值的,如果你不需要返回值,直接用runInTx就可以了

注意点:

save()、insert()、insertOrReplace()的区别:

方法 说明
save() 根据主键id判断是更新还是新增
insert() 单纯的保存,什么都没有
insertOrReplace() 有就更新,没有就新增

我们可以看下save方法:
Android系列之GreenDao基本使用(增、删、改、查)(一)_第5张图片
上面的英文的意思:根据key值判断是否更新新增,这个方法和insertOrReplace相似,但是有一些不同点,因为如果key是存在的(如果key值已经存在和,save不会去查询数据库)。
我们再看下hasKey的方法:
在这里插入图片描述
是一个抽象方法,我们看下实现类
Android系列之GreenDao基本使用(增、删、改、查)(一)_第6张图片
看到没有~~~~~~~~
这边是根据你插入的实体类的id是否为空来判断更新或者新增的。
所以,如果你只是单纯的新增话,我还是建议你直接用insert方法。

主键id为什么要Long不能写long

看到这里,不知道大家还记不记得在创建表结构那一节,我强调了主键要用Long,不要用long。
那么为什么要这么做呢?
很简单。我们把之前的Long改成long,看看会发生什么情况就知道了。这里,我可以告诉大家:跟save方法中的hasKey有关。
改成long,然后重新build一下:
在这里插入图片描述
ok 大家可以看到这边hasKey的方法变成了跑异常了。
想想也对,你如果是long类型的,怎么判断是否为空呢?

而且如果是long类型的话,新增的时候,不会自动增长,需要制定,不然会报错:

注意GreenDao的缓存

当你发现我修改数据库数据之后,查询出来的数据还是之前的数据的时候,你就要考虑到GreenDao的缓存效果。
如果去除缓存:

DaoSession.clear();//清除所有数据库表的缓存dao.detachAll()//清除某个表的所有缓存

开启GreenDao日志

QueryBuilder.LOG_SQL = true;QueryBuilder.LOG_VALUES = true;

总结

也是最近在做Android的项目,又开始重拾Android技能。我是2015年开始学习Android,实习的时候是Android 开发,到2016年之后就做java Web开发。
中间虽然也断断续续接触Android,但是所使用的的一些技巧和一些技术点都感觉比较老了。
或许有人会问:你即做Android又做Java Web,会不会两个到最后都半吊子。
其实从某种意义来说,Android也是java的一种表现方式,两者之间都有各自的表现方式,也有共同点,毕竟Android也是用java来写的。
最近我会陆陆续续更新几篇Android的文章,这几篇文章呢,都是我在项目中实际使用到的,感觉还蛮有意思的,后续会和大家一起分享。文中有什么不对的或者表述不清楚的地方,希望大家留言,我会尽快修改并回复。
GreenDao三部曲:
Android系列之GreenDao基本使用(增、删、改、查)(一)
Android系列之GreenDao连表查询(二)
Android系列之GreenDao数据升级和加密(三)

更多相关文章

  1. android中px,dp,sp的区别与使用方法
  2. Android核心分析 之一--------分析方法论探讨之设计意图
  3. android 设置颜色的三种方法
  4. android 获取设备支持的编解码器的方法
  5. Android Studio:Error:Could not find com.android.tools.build:g

随机推荐

  1. 服务器登录密码忘记了怎么办?总结办法如下
  2. 阿萨德请问日期为人
  3. 飞舞的气泡
  4. 对容器镜像的思考和讨论
  5. 对象模拟数组
  6. Java基于NIO实现聊天室功能
  7. 关于云平台,目前已售/已用的云服务器整理
  8. 【阿里云镜像】更改阿里巴巴开源镜像站镜
  9. 【阿里云镜像】更新阿里巴巴开源镜像站镜
  10. 如何学习画插画?手绘插画学习教程