greenDao使用指南-1

GreenDao

GreenDao是一个高效的数据库访问ORM框架,节省了自己编写SQL的时间,快速的增删查改等操作。

介绍就不多说,直接介绍重点吧!!!首先po一个github的地址:https://github.com/greenrobot/greenDAO

配置GreenDao

// In your root build.gradle file:
buildscript {
    repositories {
        jcenter()
        mavenCentral() // add repository
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
    }
}
 
// In your app projects build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
 
dependencies {
    compile 'org.greenrobot:greendao:3.2.2' // add library
}

注意咯,一个是添加在工程的build.gradle,一个是添加到module的build.gradle文件中.

build.gradlel里面对greenDao进行配置。配置之后就搭建好了greenDao的环境,可以自动生成相关的类。

然后你需要配置greenDao的数据库版本号以及自动生成的包名的路径,当然路径可选择性的配置。

android{
    ...
}

greendao{
    schemaVersion 2 // 数据库版本号
    daoPackage  'com.doris.sample.greendao'//greenDao 自动生成的代码保存的包名
    targetGenDir   'src/main/java' //自动生成的代码存储的路径,默认是 build/generated/source/greendao.
    generateTests false //true的时候自动生成测试单元
    targetGenDirTests: 测试单元的生成目录默认是 src/androidTest/java
}

接下来你定义自己的entity并且make project就可以开始对数据库进行操作啦。

下面对greenDao的相关知识点进行介绍:

注释

greenDAO 3 用注释去schemas 和实体类 entities.例子如下:

@Entity(nameInDb = "user_info",indexes = {
                @Index(value = "name DESC", unique = true)
        },)
public class User {
    @Id
    private Long id;
 
    @Property(nameInDb = "USERNAME") @NotNull
    private String name;
 
    @Transient
    private int tempUsageCount; // not persisted
 
   // getters and setters for id and user ...
}

@Entity将一个Java类转变成一个实体类。greenDao会根据这个生成对应的代码。PS: 必须是java类,kotlin不支持。

在Entity中我们可以配置许多信息,比如nameInDb是声明了该表数据库中的表名。
indexes 用于建立索引,索引的应用场景可用于,当你的表有多个主键的时候,来标志一条数据的唯一性,配合unique。
当然上面两个只是我们常用的属性,还有几个其他属性,目前我还没有用到:
schema = "myschema", 当你有多个schema,用这个属性来告诉数据库当前entity属于哪个schema。
active = true,用于标志某个entity是否是active的,active的实体类有删改的方法。默认是fale, 为true的时候会自动生成下面的代码在entity里面:

 /**
    * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
    * Entity must attached to an entity context.
    */
   @Generated(hash = 128553479)
   public void delete() {
       if (myDao == null) {
           throw new DaoException("Entity is detached from DAO context");
       }
       myDao.delete(this);
   }

   /**
    * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
    * Entity must attached to an entity context.
    */
   @Generated(hash = 1942392019)
   public void refresh() {
       if (myDao == null) {
           throw new DaoException("Entity is detached from DAO context");
       }
       myDao.refresh(this);
   }

   /**
    * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
    * Entity must attached to an entity context.
    */
   @Generated(hash = 713229351)
   public void update() {
       if (myDao == null) {
           throw new DaoException("Entity is detached from DAO context");
       }
       myDao.update(this);
   }

基本的属性:

@Id 标志主键

@Transient 表示不存储在数据库中

@NotNull 标志这个字段不能是null

@Property 如果定义了这个属性,那么nameInDb的值就是该列在数据表里面,该列的名称。上面的例子,username的值存储在数据表里面的USERNAME那一列。

主键的限制

当前,entity必须有一个long或者Long的属性作为主键,但是有时候我们的主键不一定是long或者Long型的可能是string呀之类的,这个时候我们就可以定义索引属性并且注明独一无二。 如下:

@Index(name = "keyword", unique = true)
private String key;

name用于指明这个索引的列名,unique表示这个指是不可重复的。

@Unique 用于标志列的值的唯一性。

greenDao尽最大的可能的合理的安排每个属性的默认值,所以一般不需要去配置每一个选项。只需要配置你需要的就可以了。

当你编写好的entity之后,只需要点击Build-> make project就可以自动生成相关的代码了。

如果你改变了已经存在的entity记得rebuild工程保证旧的entity类被clean掉了。

记住不要随意修改注明了@Generated的代码,这样会导致报错,

Error:Execution failed for task ':app:greendao'.
> Constructor (see ExampleEntity:21) has been changed after generation.
Please either mark it with @Keep annotation instead of @Generated to keep it untouched,
or use @Generated (without hash) to allow to replace it.

解决这个的办法有两个:

  1. 将@Generated注释改回去,或者将自动生成的代码删掉,然后他会自动rebuild在下次build工程的时候。
  2. 将@Generated改成@Keep,这样greenDao将不会检查这段代码,但是这样可能会导致实体和greenDao其他的契合部分。另外,未来版本的greenDAO可能会在生成的方法中使用不同的代码。最好是不要修改这个,如果实在要修改,建议编写测试单元,测试一下确保不会有问题。

@Keep在新版本里面已经被淘汰了,如果当gradle检测到有@Keep会将他替换成@Transient!!!注意啦!!!

实体类建立好了,那么如何操作数据库,通过什么访问数据库呢,先来介绍一下greenDao的几个关键的类。

关键的几个类

DaoMaster

greenDao的入口,持有数据库(SQLiteDatabase)对象 并且 管理Schema的DAO类(不是对象)。持有静态的创建于删除表的方法。内部类OpenHelper以及DevOpenHelper实现了SQLiteOpenHelper,创建了数据库模式(Schema)。进行数据库连接。

DaoSession

管理特定模式的所有可用的DAO对象,通过getter方法可以获取到DAO对象。提供了增删查改实体的方法。

DAOs

全称Data access Objects,数据访问对象,对于每一个实体类,greenDao生成一个DAO,持有很多持久性的方法,例如 count, loadAll以及insertInTx。

Entities

持久化对象(与数据库对应的实体类),对应数据库里面的一行。

在用数据库之前首先需要初始化数据库,一般我们在Application里面进行数据库的数据化,并且只初始化一次。

// do this once, for example in your Application class
helper = new DaoMaster.DevOpenHelper(this, "notes-db", null);
db = helper.getWritableDatabase();
daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();

然后要操作对应的对象的时候只需要获取到对应的Dao对象即可:

// do this in your activities/fragments to get hold of a DAO
noteDao = daoSession.getNoteDao();

Session

DaoSession是greenDao重要的接口之一,提供了基本的实体类操作,Daos提供了更多的完整的操作。
获取Session

daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();

请注意,数据库连接属于DaoMaster,因此多个会话引用相同的数据库连接。 因此,可以很快创建新的会话。 但是,每个会话都会分配内存,通常是实体的会话“缓存”。

Identity scope and session “cache”

如果有两个查询返回相同的数据库对象,那么您使用的Java对象有多少个:一个还是两个?它完全取决于身份范围。

greenDAO中的默认值(行为是可配置的)是多个查询返回对相同Java对象的引用。例如,从ID为42的USER表中加载一个User对象为这两个查询返回相同的Java对象。

这个副作用是某种实体“缓存”。如果一个实体对象仍然在内存中(greenDAO在这里使用弱引用),则该实体不会再构造。另外,greenDAO不执行数据库查询来更新实体值。相反,对象会从会话缓存中“立即”返回,这会比一个或两个数量级更快。

清除identity scope

清除整个session,没有缓存对象返回

daoSession.clear(); 

清除单个Dao的identity scope ,这样某个dao不会有缓存对象返回

noteDao = daoSession.getNoteDao();
noteDao.detachAll();

Queries

在GreenDao,你可以自己写原生的查询语句,也可以通过QueryBuilderAPI来查询。

Query用于查询的类

  • QueryBuilder

SQL的语法错误只有在run time的时候才会提示,但是用greenDaoQueryBuilder可以在编译的时候就检测到错误。

查询范例:

List<User> joes = userDao.queryBuilder()
  .where(Properties.FirstName.eq("Joe"))
  .orderAsc(Properties.LastName)
  .list();

用对应的Dao对对应的表进行查询操作,调用qureyBuilder方法,where是查询条件,可以有多个查询条件,用逗号分隔开来,如下:

List<User> joes = userDao.queryBuilder()
  .where(Properties.FirstName.eq("Joe"), Properties.AGE.eq("10")
  .orderAsc(Properties.LastName)
  .list();

上面语句查询lastname是joe的并且年龄是10岁的人。

复杂的不是and连接的查询语句可以如下查询:

多个条件查询:

QueryBuilder<User> qb = userDao.queryBuilder();
qb.where(Properties.FirstName.eq("Joe"),
qb.or(Properties.YearOfBirth.gt(1970),
qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10))));
List<User> youngJoes = qb.list();

上面语句应该如下解释

 First name is "Joe" AND (year of birth is greater than 1970 OR (year of birth is 1970 AND month of birth is equal to or greater than 10))

即找出first name是joe的然后出生于1970年10以后的。

order

排序,我们可以对查询的结果进行排序。

orderAsc(依据的属性名称,可以有多个属性),正序 orderDesc 倒序

// order by last name
queryBuilder.orderAsc(Properties.LastName);
 
// in reverse
queryBuilder.orderDesc(Properties.LastName);
 
// order by last name and year of birth
queryBuilder.orderAsc(Properties.LastName).orderDesc(Properties.YearOfBirth);

greenDAO使用的默认排序规则是COLLATE NOCASE,尽管它可以使用stringOrderCollation()进行定制。 有关影响结果顺序的其他方法,请参见QueryBuilder类文档。

limit

当你根据条件查询,返回N条数据的时候,但是你只想要里面的前十个的时候,这个时候用limit可以限制获取 n条数据,不用for循环cursor。

limit

limit(int)限制查询返回的条数。

需求千变万化的,有时候你需要的不是前面的n条,而是从位置m开始的n条数据,这个时候就可以用offset 设置数据返回的偏移值。

offset(int)

设置返回数据的起始偏移值,得到offset开始的n条数据。必须要结合limit(int n)来使用

queryBuilder().where(Properties.YearOfBirth.gt(2001)).offset(3).limit(10)

上面例子是取出出生年份大于2001年的第3个开始的十个人。

查询条件总结

  • eq : Properties.YearOfBirth.eq(2001): 等于
  • notEq : 不等于
  • like:模糊查询 记住模糊查询,string要用夹在%key%中间。
xxDao.queryBuilder().where(Properties.FirstName.like("%doris%")).list();

查询FristName包含doris的人。

  • BETWEEN ... AND ... ...和...之间。
  • IN(..., ..., ...) 在给出的value的范围内的符合项
  • gt 大于
  • ge 大于等于
  • lt 小于
  • le 小于等于
  • isNull 不是空的

查询有懒查询,也叫延迟查询吧,我觉得,就会你先执行了查询语句但是呢只有在你用的时候才会加载到内存,就类似于懒加载。

  • list() 不是懒加载,正常查询,查询结果立马加载到内存。
  • listLazy() 实体按需加载到内存中。 一旦列表中的元素第一次被访问,它将被加载并缓存以供将来使用。 必须关闭。
  • listLazyUncached() 一个“虚拟”实体列表:对列表元素的任何访问都会导致从数据库加载其数据。 必须关闭。
  • listIterator() 让我们通过按需加载数据(懒惰地)来遍历结果。 数据没有被缓存。 必须关闭。

greenDao还支持多线程查询以及重复使用Query对象,这个我还没用到,用到给大家再深入讲解一下哈!

原始查询

方法1:

Query<User> query = userDao.queryBuilder().where(
  new StringCondition("_ID IN " +
    "(SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)")
).build();

方法2:
queryRawqueryRawCreate

Query<User> query = userDao.queryRawCreate(
  ", GROUP G WHERE G.NAME=? AND T.GROUP_ID=G._ID", "admin"
);

debug查询

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

设置这两个属性就可以看到log、

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • greenDAO官方主页:http://greendao-orm.com/ 官方主页新地址:http://gree...
    sunny_zhang阅读 10,118评论 12 49
  • LZ-Says:撸文不易,且行且珍惜~ 每日一笑: 这里写图片描述 前言 端午三天,去天津玩了一圈,出去走走,放松...
    静心Study阅读 7,330评论 8 72
  • greenDAO greenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案。它...
    蕉下孤客阅读 16,077评论 18 104
  • 大神们都说GreenDao性能最好,使用方便,最近在做一个项目,刚好用到操作本地数据库,so机缘巧合,开始学习Gr...
    冯奕欢阅读 10,729评论 2 7
  • 最近的电视剧,《那年花开月正圆》闹得那么火,我禁不住诱惑,所以十一长假我也追了好几集。 特地我还查了周莹的原型,当...
    李晴天阅读 191评论 1 1