GreenDao概要

引用 greenDAO

当前的 greenDAO 要求 gradle 的版本至少是 3.3 ,我升级 gradle 折腾了半个小时,升级 gradle 的 方法和 gradle下载地址

// In your project level build.gradle file:
buildscript {
    repositories {
        jcenter()
        mavenCentral() 
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1' 
    }
}

// In your app level build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao'

dependencies {
    compile 'org.greenrobot:greendao:3.2.0' 
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

实体类的生成

@Entity
public class StudentMsgBean {
    @Id
    private Long id;
    @Property(nameInDb = "STUDENTNUM")
    private String studentNum;
    @Property(nameInDb = "NAME")
    private String name;
    @Generated(hash = 381350025)
    public StudentMsgBean(Long id, String studentNum, String name) {
        this.id = id;
        this.studentNum = studentNum;
        this.name = name;
    }
    @Generated(hash = 160565988)
    public StudentMsgBean() {
    }
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getStudentNum() {
        return this.studentNum;
    }
    public void setStudentNum(String studentNum) {
        this.studentNum = studentNum;
    }
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

实体类中常用的注解:

@Entity  表明这个实体类会在数据库中生成一个与之相对应的表。 
@Id  对应数据表中的 Id 字段,有了解数据库的话,是一条数据的唯一标识。 
@Property(nameInDb = “STUDENTNUM”)  表名这个属性对应数据表中的 STUDENTNUM 字段。 
@Property  可以自定义字段名,注意外键不能使用该属性 
@NotNull  该属性值不能为空 
@Transient  该属性不会被存入数据库中 
@Unique  表名该属性在数据库中只能有唯一值

当你写完实体类中的属性之后,点击编译,就会自动生成相应的 setter 和 getter 方法,至于那些 hash 值是自动赋值上去的。并且在该目录下生成 DaoMaster 和 DaoSession 这两个类用于初始化数据库。

增删改查

一般数据库的操作都离不开增删改查,那么我们就从这开始。

初始化

DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(getApplicationContext(), "student.db", null);
DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());
DaoSession daoSession = daoMaster.newSession();
 
 
  • 1
  • 2
  • 3

如果实体类有更新,那么要调用 daoSession.clear() 清除缓存,才能得到更新。 

StudentMsgBeanDao msgBeanDao = daoSession.getStudentMsgBeanDao();
StudentMsgBean studentMsgBean = new StudentMsgBean();
studentMsgBean.setName("zone");
studentMsgBean.setStudentNum("123456");
msgBeanDao.insert(studentMsgBean);
 
 
  • 1
  • 2
  • 3
  • 4
  • 5

                List<StudentMsgBean> list = msgBeanDao.queryBuilder()
                        .build().list();
                for (int i = 0; i < list.size(); i++) {
                    Log.d("zoneLog", "studentNumber: " + list.get(i).getStudentNum());
                    Log.d("zoneLog", "name: " + list.get(i).getName());
                    if (i == 0) {
                        msgBeanDao.deleteByKey(list.get(0).getId());//通过 Id 来删除数据
//                        msgBeanDao.delete(list.get(0));//通过传入实体类的实例来删除数据
                    }

                }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

                List<StudentMsgBean> list = msgBeanDao.queryBuilder()
                        .build().list();
                for (int i = 0; i < list.size(); i++) {
                    Log.d("zoneLog", "studentNumber: " + list.get(i).getStudentNum());
                    Log.d("zoneLog", "name: " + list.get(i).getName());
                    if (i == 0) {
                        list.get(0).setName("zone==========>");
                        msgBeanDao.update(list.get(0));
                    }
                }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

                List<StudentMsgBean> list = msgBeanDao.queryBuilder()
                        .offset(1)//偏移量,相当于 SQL 语句中的 skip 
                        .limit(3)//只获取结果集的前 3 个数据
                        .orderAsc(StudentMsgBeanDao.Properties.StudentNum)//通过 StudentNum 这个属性进行正序排序
                        .where(StudentMsgBeanDao.Properties.Name.eq("zone"))//数据筛选,只获取 Name = "zone" 的数据。
                        .build()
                        .list();
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

需要注意的是 offset 是要和 limit 配合使用的。

  • list() 所有实体会直接加载到内存中。
  • listLazy() 当你需要使用时,才会加载,会自动缓存。使用完必须关闭。
  • listLazyUncached() 如你所见,就是不会缓存的意思。使用完必须关闭。
  • listIterator() 通过迭代器遍历结果集,不会缓存。使用完必须关闭。
  • unique() 返回一个或者零个结果
  • uniqueOrThrow() 返回非空的结果,否则抛出异常

listLazy(), listLazyUncached(), listIterator() 这三个方法都使用了 LazyList.class 这个类。它持有了数据库游标的引用,这就是为什么要关闭的原因。当然,当你遍历完所有的结果集,它是会自动关闭的。如果没有遍历完,就得手动关闭了。

当多次使用到查询的时候,更加高效的方法是新建一个 Query 对象。然后根据需要更改相应的查询参数。

Query<StudentMsgBean> query= msgBeanDao.queryBuilder().where(StudentMsgBeanDao.Properties.Name.eq("zone")).build();
List<StudentMsgBean> list1 = query.list();
query.setParameter(0, "zone123");
list1 = query.list();
 
 
  • 1
  • 2
  • 3
  • 4

query.setParameter(index, condition); 
来说说这行代码的参数,首先 index 是从 0 开始算的,它是基于你所传的参数的顺序来定的。然后是 condition 这个就是你要修改的相应参数。这些算是基础操作了,那么下面我们来更深一步地学习

1:1 查询

其实就是两张表联表查询。想象一下你高中的时候,每次到期末,学校都会发一张期末各科的成绩单给你,假定你只要学习英语和数学这两门学科,一个学生对应一张成绩单。那么下面的代码就是描述这种情况的。

学生实体类:

@Entity
public class StudentMsgBean {
    @Id
    private Long id;
    @Property(nameInDb = "STUDENT_NUM")
    private String studentNum;
    @Property(nameInDb = "NAME")
    private String name;
    @Property(nameInDb = "SCORE_ID")
    private Long scoreId;
    @ToOne(joinProperty = "scoreId")
    private ScoreBean mScoreBean;
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

成绩实体类:

@Entity
public class ScoreBean {
    @Id
    private Long id;
    private String mathScore;
    private String englishScore;
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

如上两段代码是两个实体类,为了方便查看,我进行了简化。通过让第一个实体类持有一个外键,这个外键是第二个实体类的 id 。让 greenDAO 能通过这个外键来查询到相应的数据。那么来看一下小 demo :

//              存入一个数据
StudentMsgBean studentMsgBean = new StudentMsgBean();
studentMsgBean.setName("zone");
studentMsgBean.setStudentNum("123456");
ScoreBean scoreBean = new ScoreBean();
scoreBean.setEnglishScore("120");
scoreBean.setMathScore("1000");
scoreBeanDao.insert(scoreBean);
ScoreBean scoreBean1 = scoreBeanDao.queryBuilder().unique();
if (scoreBean1 != null) {
    studentMsgBean.setScoreId(scoreBean1.getId());
    studentMsgBean.setMScoreBean(scoreBean);
    msgBeanDao.insert(studentMsgBean);
}
//                查询数据
List<StudentMsgBean> list = msgBeanDao.queryBuilder().list();
for (int i = 0; i < list.size(); i++) {
    Log.d("zoneLog", "studentNumber: " + list.get(i).getStudentNum());
    Log.d("zoneLog", "name: " + list.get(i).getName());
    Log.d("zoneLog", "english: " + list.get(i).getMScoreBean().getEnglishScore());
    Log.d("zoneLog", "math: " + list.get(i).getMScoreBean().getMathScore());
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

这里写图片描述

1:n

想象一下你写博客,你写了 n 篇博文,那么对于你来说,就是一对多的关系,那么接下来的 demo 就是关于这个的。实现一对多的方式有两种,先看看第一种

第一种:

作者实体类如下:(此处省略了 setter getter 等方法)

@Entity
public class Author {
    @Id
    private Long id;
    private String name;
    private String sex;
    @ToMany(referencedJoinProperty = "authorId")
    private List<Post> posts;
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

博文实体类如下:(此处省略了 setter getter 等方法)

@Entity
public class Post {
    @Id
    private Long id;
    private String content;
    private Long authorId;
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
AuthorDao authorDao=daoSession.getAuthorDao();
PostDao postDao = daoSession.getPostDao();

Author author = new Author();//存贮一个作者
author.setName("zone");
author.setSex("boy");
authorDao.insert(author);
Author authorByQuery = authorDao.queryBuilder().where(AuthorDao.Properties.Name.eq("zone"), AuthorDao.Properties.Sex.eq("boy")).unique();

Post firstPost = new Post();//写一篇文章
firstPost.setAuthorId(authorByQuery.getId());
firstPost.setContent("第一篇文章!");
Post secondPost = new Post();//写一篇文章
secondPost.setAuthorId(authorByQuery.getId());
secondPost.setContent("第二篇文章!");
postDao.insertInTx(firstPost,secondPost);//存储文章

Author authorResult = authorDao.queryBuilder().where(AuthorDao.Properties.Name.eq("zone"), AuthorDao.Properties.Sex.eq("boy")).unique();//查询存储的结果
L.d(authorResult.getName());
L.d(authorResult.getSex());
for (int i = 0; i < authorResult.getPosts().size(); i++) {
    L.d(authorResult.getPosts().get(i).getContent());
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

这里写图片描述

第二种方法:

referencedJoinProperty 是 @JoinProperty 的特例,这是一种自定义关联的方式。下面的代码中是通过 alias 和 authorAlias 进行关联。如果将 alias 改为 id ,将 authorAlias 改为 authorId ,那么第一种方法和第二种方法是等价的。

@Entity
public class Author {
    @Id
    private Long id;
    private String name;
    private String sex;
    private String alias;
    @ToMany(joinProperties = {
            @JoinProperty(name = "alias" ,referencedName = "authorAlias")
    })
    private List<Post> posts;
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
@Entity
public class Post {
    @Id
    private Long id;
    private String content;
    private Long authorId;
    private String authorAlias;
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

RxDao

最近响应式编程在 Android 这边也是火热朝天,那么我们也一起来探索一下 greenDAO 的 Rx 版。 
初始化

DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(getApplicationContext(), "student.db", null);
DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());
DaoSession daoSession = daoMaster.newSession();
RxDao<Author,Long> authorLongRxDao = daoSession.getAuthorDao().rx();
 
 
  • 1
  • 2
  • 3
  • 4

  authorLongRxDao
        .insert(author)//保存单一实例
//      .insertInTx(author1,author2)//保存多个实例
        .subscribeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<Author>() {
               @Override
               public void call(Author author) {
//              获取插入后的结果集
                }
         });
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

  authorLongRxDao
        .delete(author)//通过一个具体的实例来进行删除
//      .deleteByKey(key)//通过 id 来进行删除
//      .deleteAll()//删除所有
        .subscribeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<Void>() {
            @Override
            public void call(Void aVoid) {

            }
         });
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

author.setName("asd");//这是一个查询到的实例 author
authorLongRxDao
        .update(author)//更新单个
//      .updateInTx(author1,author2)//更新多个
        .subscribeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<Author>() {
            @Override
            public void call(Author author) {
//              获取更新后的结果集
            }
         });
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

RxQuery<Author> authorRxQuery = daoSession.getAuthorDao().queryBuilder().rx();
authorRxQuery
        .unique()//获取单一结果集
//      .list()//获取多个结果集
//      .oneByOne()//一次发射一个实例
        .subscribeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<Author>() {
            @Override
            public void call(Author author) {

            }
        });

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值