GreenDao入门

1. 什么是greenDao

弄明白greenDao以前咱们应该先了解什么是ORM(Object Relation Mapping 即 对象关系映射),说白了就是将面向对象编程语言里的对象与数据库关联起来的一种技术,而greenDao就是实现这种技术之一,因此说greenDao其实就是一种将java object 与SQLite Database关联起来的桥梁,它们之间的关系 以下图所示;java

2. 为何要使用greenDao

greenDao能够说是当今最流行,最高效并且还在迭代的关系型数据库。并且greenDao3.0还支持RxJava操做,greenDao如此受欢迎离不开如下几点:android

  • 存取速度快数据库

    每秒中能够操做数千个实体 下图是几种常见关系型数据库性能比较;

  • 支持数据库加密编程

    支持android原生的数据库SQLite,也支持SQLCipher(在SQLite基础上加密型数据库)。
  • 轻量级segmentfault

    greenDao的代码库仅仅100k大小
  • 激活实体缓存

    处于激活状态下的实体能够有更多操做方法
  • 支持缓存session

    可以将使用的过的实体存在缓存中,下次使用时能够直接从缓存中取,这样可使性能提升N个数量级
  • 代码自动生成多线程

    greenDao 会根据modle类自动生成实体类(entities)和Dao对象,而且Dao对象是根据entities类量身定作的而且一 一对应。

3. 怎样使用greenDao

3.1 入门

3.1.1 配置GreenDaoapp

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
     classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0'//greenDao生产代码插件
    }
apply plugin: 'org.greenrobot.greendao'//greendao插件
dependencies {
      compile 'org.greenrobot:greendao:3.2.0'

配置数据库信息maven

greendao {
        //数据库schema版本,也能够理解为数据库版本号
        schemaVersion 2
        //设置DaoMaster 、DaoSession、Dao包名
        daoPackage 'com.qhn.bhne.footprinting.db'
        //设置DaoMaster 、DaoSession、Dao目录
        targetGenDir 'src/main/java'
        //设置生成单元测试目录
//    targetGenDirTest
        //设置自动生成单元测试用例
//    generateTests
    }

到这里数据库基本配置已经完成,接下来让咱们一块儿来了解下greenDao的核心类该怎样使用吧。
3.1.2 核心类介绍

  • DaoMaster:

    • 是GreenDao的入口也是greenDao顶级对象,对于一个指定的表单持有数据库对象(SQLite数据库)而且可以管理DAO类
    • 可以建立表和删除表
    • 其内部类OpenHelper 与DevOpenHelper是建立SQlite数据库的SQLiteOpenHelper的具体实现
  • DaoSession:

    • 对于一个指定的表单能够管理全部的Dao 对象。
    • 也可以对实体类执行 insert ,load,update,refresh.delete操做。
    • DaoSession也能跟踪 identity scope:即session查询后的实体会存在缓存中,并给该实体生成一个flag来追踪该实体,下次再次查询时会直接从缓存中取出来而不是从数据库中取出来
  • DAOS

    • 可以持久访问和查询实体类
    • 比起DaoSession有更多的持久化方法 count, loadAll,insertInt等等;
  • Entities - 自动生成的代码,通常状况下与javaBean对象的属性一一对应。

3.1.3 构建Model类

Molde类须要用java类来定义而且能够经过GreenDao中的注释来代表Model中的每一个属性在数据库的中该如何定义;定义model类后点击Make project选项GreenDao就会自动生成DaoMaster,DaoSession,和DAOS类,生成的代码将会保存在预先在budle gradle中设置的位置

  • 实体和注释

    GreenDao 经过注释来定义表单与实体
@Entity
public class User { 
        @Id 
        private Long id;  private String name; 
        @Transient 
        private int tempUsageCount; // 没有存入数据库中
 }

@Entity

  • 告诉GreenDao 该Bean类须要持久化。只有使用@Entity注释的Bean类才能被dao类操做;
  • @Entity能够在不使用参数下使用,可是也能够给Entity配置参数,其参数以下
//若是该实体属于多个表单,可使用该参数; 
schema = "myschema",  
// 该实体属于激活状态,激活状态的实体有更新,删除,刷新方法; 
active = true,  
// 给这个表指定一个名字,默认状况下是名字是类名 
nameInDb = "AWESOME_USERS",
 // 能够给多个属性定义索引和其余属性.
 indexes = { @Index(value = "name DESC", unique = true) },  
//是否使用GreenDao建立该表.
 createInDb = false,   
// 是否全部的属性构造器都应该被生成,无参构造器老是被要求
 generateConstructors = true,  
// 若是该类中没有set get方法是否自动生成 
generateGettersSetters = true
  • 基本注释属性

    • @ID 通常会选择long/Long属性做为Entity ID(即数据库中的主键)autoincrement=true表示主键会自增若是false就会使用旧值
    • @Property 能够自定义一个该属性在数据库中的名称,默认状况下数据库中该属性名称是Bean对象中的 属性名可是不是以驼峰式而是以大写与下划线组合形式来命名的好比:customName将命名为 CUSTOM_NAME;注意:外键不能使用该属性;
    • @NotNull 确保属性值不会为null值;
    • @Transient 使用该注释的属性不会被存入数据库中;
    • @Unique 将属性变成惟一约束属性;也就是说在数据库中该值必须惟一
    • @Generated 提示开发者该属性不能被修改;而且实体类的方法,属性,构造器一旦被@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.
这是由于在经过javabean对象自动生成entities类时,greenDao会增长实体类代码,@Generated注释部分与GreenDao增长的代码相关,胡乱修改@Generated代码,就会致使entities部分属性与javabean不匹配致使报错;有俩种方法能够避免这种错误

    *   还原**@Generated** 改动的部分,固然你也能够彻底删除@Generated 注释的部分下一次 app build时将会自动生成;

    *   使用**@Keep** 代替**@Generated** 这将告诉greenDao 不会使用该属性注释的代码,可是这种改变可能会破坏entities类和greenDAO的其余部分的链接;注意:默认状况下 greenDao会使用合理的默认值去设置实体类,所以开发者不须要为每一个属性都添加注释
@Entity
public class User { 
      @Id(autoincrement = true)
       private Long id;  
      @Property(nameInDb = "USERNAME") 
       private String name;  
      @NotNull 
      private int repos;  
      @Transient 
      private int tempUsageCount; 
 ...}
    • *
  • 主键限制

    每一个实体类都应该有一个long或者LONG型属性做为主键;若是你不想用long或者LONG型做为主键,你可使用一个惟一索引(使用@Index(unique = true)注释使普通属性改变成惟一索引属性)属性做为关键属性。
@Id
private Long id; 
@Index(unique = true)
private String key;
  • 索引属性
    使用@Index 能够将一个属性变为数据库索引;其有俩个参数

    • name :不使用默认名称,自定义索引名称
    • unique : 给索引增长一个惟一约束,迫使该值惟一
@Entity
public class User { 
@Id 
private Long id;
 @Index(unique = true)
 private String name;
}
  • 核心代码初始化
    建立数据库过程

    // 下面代码仅仅须要执行一次,通常会放在application
    helper = new DaoMaster.DevOpenHelper(this, "notes-db", null);
    db = helper.getWritableDatabase();
    daoMaster = new DaoMaster(db);
    daoSession = daoMaster.newSession();
    // 在activity或者fragment中获取Dao对象
    noteDao = daoSession.getNoteDao()
完成以上全部工做之后,咱们的数据库就已经自动生成了,接下来就能够对数据库进行操做了;
  • 增删改查
    greenDao的增,删 ,改操做比较简单分别调用insert(),delete(),update()方法便可,save()方法比较特殊既能执行插入操做也能执行修改操做这个具体的能够查看greenDaoAPI

    • Query
      与原生SQLitedatabases的查询操做相比,greenDao Query简直不能再简单;greenDao 使用QueryBuilder构建查询语句也支持原生的SQL查询语句

      • 简单的查询语句 在用户表中查询叫姓“Joe”的全部的用户:

        List joes = userDao.queryBuilder() 
        .where(Properties.FirstName.eq("Joe")) 
        .orderAsc(Properties.LastName) .list();
*   嵌套挑去查询语句:查询一个出生在1970年10月或者之后的"joe"用户
QueryBuilder qb = userDao.queryBuilder();
qb.where(Properties.FirstName.eq("Joe"),//第一个约束条件姓乔
qb.or(Properties.YearOfBirth.gt(1970),//或者出生日期大于1970年
qb.and(Properties.YearOfBirth.eq(1970), 
Properties.MonthOfBirth.ge(10))//而且在1970年出生 可是月份大于
10月的));
List youngJoes = qb.list();
greenDao除了eq()操做以外还有不少其余方法大大方便了咱们平常查询操做好比:
    *   eq():==
    *   noteq():!=
    *   gt(): >
    *   lt():<
    *   ge:>=
    *   le:<=
    *   like():包含
    *   between:俩者之间
    *   in:在某个值内
    *   notIn:不在某个值内
  • 分页查询

    • limit(int): 限制查询的数量;
    • offset(int): 每次返回的数量; offset不能单独使用;
  • 查询与LazyList类

    • Query : Query类表示一个查询可以执行不少次;而当经过QueryBuilder的任何查询方法(eg:list())来获取查询结果时,querybuilder都会 在其内部建立Query来执行查询语句的;若是执行屡次查询应该使用Query对象; 若是只想获取一个结果时可使用Query(or QueryBuilder)中的unique()方法;
    • LazyList : 能够经过如下方法获取查询结果集合;

      • list() 缓存查询结果;list()类型通常为ArrayList
      • listLazy() 懒查询,只有当调用list()中的实体对象时才会执行查询操做而且只缓存第一次被查询的结果,须要关闭
      • listlazyUncached() 懒查询,只有当调用list()中的实体对象时才会执行查询操做而且不缓存;
      • listIterator() 对查询结果进行遍历,不缓存,须要关闭;

后面三个方法是LazyList类中的方法,LazyList为了执行不一样的缓存策略其内部持有数据库的cursor对象;通常状况下这三个方法执行完毕后会自动关闭cursor;可是防止在尚未执行完查询结果时,对象被终结cursor仍是没法被关闭的状况发生,须要手动关闭close();

  • 屡次执行查询语句

    Query对象一旦生成就能屡次被使用,你也能够为下一次查询增长查询条件
// fetch users with Joe as a first name born in 1970Query 
query = userDao.queryBuilder().where( 
Properties.FirstName.eq("Joe"), 
Properties.YearOfBirth.eq(1970)).build();List joesOf1970 = 
query.list(); // using the same Query object, we can change the 
parameters// to search for Marias born in 1977 
later:query.setParameter(0, "Maria");query.setParameter(1, 
1977);List mariasOf1977 = query.list();
  • 在多线程执行查询
    若是有多条线程执行查询语句时须要调用forCurrentThread()方法将query对象与当前线程进行绑定,若是其余线程修改该Query对象,greenDao将会抛出一个异常;forCurrentThread()方法经过将Query建立时的时间做为 query标识;
  • 使用SQL查询
    若是QueryBuilder不能知足需求可使用如下俩种方法来实现你的需求;

    • 首选方法用SQL语句:

      Query query = userDao.queryBuilder().where( new 
      StringCondition("_ID IN " + "(SELECT USER_ID FROM 
      USER_MESSAGE WHERE READ_FLAG = 0)")).build();
*   备选方法 :
    使用queryRaw 或者queryRawCreate:
Query query = userDao.queryRawCreate( ", GROUP G WHERE 
G.NAME=? AND T.GROUP_ID=G._ID", "admin");

好了这一期的GreenDao的介绍到这里就结束了,本期主要讲解了greenDao的基本概念与基本操做,下一期(史上最高效的ORM方案——GreenDao3.0高级用法)我会介绍GreenDao的高级操做:session缓存多表查询多表关联自定义参数类型。若是你以为本篇本章有什么不足的地方欢迎在评论区留言;

相关文章
相关标签/搜索