Android系列之GreenDao基本使用(增、删、改、查)(一)

背景:

最近在搞一个设备权限同步的功能:设备是一个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路径,看看有没有生成对应的文件。类似于:
在这里插入图片描述
一个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<>
likeLIKE
betweenBETWEEN … AND …
inIN (…, …, …)
notInNOT IN (…, …, …)
gt>
lt<
ge>=
le<=
isNullIS NULL
isNotNullIS NOT NULL

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

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

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

2. QueryBuilder的使用

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

 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。
截图为证
在这里插入图片描述
好了,知道了这些方法之后,我们自己就可以根据需求灵活运用了。

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方法:
在这里插入图片描述
上面的英文的意思:根据key值判断是否更新新增,这个方法和insertOrReplace相似,但是有一些不同点,因为如果key是存在的(如果key值已经存在和,save不会去查询数据库)。
我们再看下hasKey的方法:
在这里插入图片描述
是一个抽象方法,我们看下实现类
在这里插入图片描述
看到没有~~~~~~~~
这边是根据你插入的实体类的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
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值