GreenDao3.0的使用

GreenDao3.2的使用

一、简介

1.1 GreenDao

简介:GreenDao是一个简化数据库开发的ORM来(对象关系映射)源框架。
GreenDao官网,点击这里跳转

ORM优点:
1. 让业务代码访问对象,而不是数据库表;
2. 隐藏了面向对象的逻辑SQL查询详情;
3. 无需处理数据库实现。

GreenDao相对于原生API的优势:
1. 不需要手动拼sql;
2. 将数据库中的数据转换为相应的对象;
3. 实现级联查询。

1.2 为什么选择使用GreenDao

主流的ORM框架:OrmLite、SugarORM、LitePal、GreenDao。

GreenDao相对于其他ORM框架的优势:
1. 性能好、内存开销小;
2. 流行(遇到问题可以求助于别人);
3. 文档比较完善;
4. 使用简单;
5. 拓展性好。

二、gredle相关配置

2.1 主项目添加

在module的build.gredle 文件中的dependencies标签中添加:

dependencies {
    compile'org.greenrobot:greendao:3.2.0'
}

2.2 添加插件

在root的build.gradle 文件添加:

dependencies {
    classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0'
}

2.3 在module中应用插件

apply plugin: 'org.greenrobot.greendao'

2.4 greendao-generator

在多数情况下使用Gradle plugin就可以满足,但是一些高级特性目前仅由greendao-generator支持,例如multiple schemas。可以根据需求判断是否添加。

dependencies {
    compile 'org.greenrobot:greendao-generator:3.2.0'
}

2.5 自定义路径

在module的build.gredle 文件根目录下添加:

greendao {
    schemaVersion 
    targetGenDir ''
    daoPackage ''
}

参数含义:

1. schemaVersion:指定数据库schema版本号,迁移等操作会用到。
2. targetGenDir:生成数据库文件的目录。
2. daoPackage:dao的包名,包名默认是entity所在的包。 

例如:


三、实体类生成

3.1 创建一个实体类

常用注解:

一:实体注解

  • @Entity:表明这个实体类会在数据库中生成一个与之相对应的表。

    1. nameInDb:可以自定义表名,表名该实体对应数据库中的那张表,默认为实体类名。
    2. indexes:定义索引,这里可跨越多个列。
    3. createInDb:如果是有多个实体都关联这个表,可以把多余的实体里面设置为false避免重复创建(默认是true)。
    4. schema:一个项目中有多个schema时,标明要让这个dao属于哪个schema。
    5. active:是否应该生成更新/删除/刷新方法。如果Entity定义了 @ToOne 或 @ToMany关系,那么独立于该值是有效的。意为是否支持实体类之间update,refresh,delete等操作。

二:基础属性注解

1. @Id:对应数据表中的主键,是一条数据的唯一标识。如果实体没有声明主键,默认创建创建Long类型主键"_id"自增。使用Long类型主键时可以通过@Id(autoincrement = true)设置为自增。
2. @Property(nameInDb = "USER_NAME" ):可以自定义字段名,注意外键不能使用该属性。表名这个属性对应数据表中的 USER_NAME 字段。
3. @NotNull:该属性值不能为空。
4. @Transient:该属性不会被存入数据库中。
5. @Unique:表明该属性在数据库中只能有唯一值。
6. @Index:创建一个索引。通过name设置索引别名,也可以通过unique给索引添加约束。
7. @Convert:指定一个PropertyConverter用于支持自定义类型(没用过)。

三:关系注解

1. @ToOne:定义自己与一个实体对象的关系。
2. @ToMany:定义自己与多个实体对象的关系。@ToMany的属性referencedJoinProperty,类似于外键约束。
3. @JoinProperty:对于更复杂的关系,可以使用这个注解标明目标属性的源属性。
4. @JoinEntity:如果你在做多对多的关系,有其他的表或实体参与,可以给目标属性添加这个额外的注解。
5. @OrderBy:指定{@ToMany}关系的相关集合的排序。**(propertyA, propertyB)默认为按主键ASC排序**

四:派生注解

1. @Generated:这个是build后greendao自动生成的,这个注解理解为防止重复,每一块代码生成后会加个hash作为标记。 官方不建议你去碰这些代码,改动会导致里面代码与hash值不符。

3.2 Make module

build -> Make module

会在build.gredle配置的路径(目录2.5)下创建一下文件,实体类也会自动生成一些代码:

四、初始化

4.1 初始化

4.2 拿到表对应的Dao对象


五、简单使用

5.1 增

5.1.1 inser()

public long insert(T entity) {}

说明:将实体数据插入到相应的表中,返回:新插入实体的行ID(默认从1开始)。

5.1.2 insertInTx()

public void insertInTx(T... entities) {}

public void insertInTx(Iterable<T> entities) {}

public void insertInTx(Iterable<T> entities, boolean setPrimaryKey) {}

说明:使用事务将给定实体插入数据库中。批量添加。

5.1.3 insertOrReplace()

public long insertOrReplace(T entity) {}

说明:将实体数据插入或替换到相应的表中(以主键为依据,当主键重复时替换),返回新插入实体的行ID。

5.1.4 insertOrReplaceInTx()

public void insertOrReplaceInTx(T... entities) {}

public void insertOrReplaceInTx(Iterable<T> entities) {}

public void insertOrReplaceInTx(Iterable<T> entities, boolean setPrimaryKey) {}

说明:使用事务插入或替换数据库中给定的实体(以主键为依据,当主键重复时替换)。批量添加。

5.1.5 save()

public void save(T entity) {}

说明:类似于insertOrReplace()方法,但比它更有效率,因为当key已经存在时,不需要查询直接更新。建议使用此方法。

5.1.6 insertWithoutSettingPk()

public long insertWithoutSettingPk(T entity) {}

说明:将一个实体插入到相应的表中,而不需要设置主键属性。返回:新插入实体的行ID。注意:这可能会更快,但实体不应该再使用了。实体也不会附加到标识作用域。仅对主键为Long类型自增有效,String类型主键会Error。

5.2 删

5.2.1 deleteAll()

public void deleteAll() {}

说明:删除相应表的全部数据(清空相应表)。

5.2.2 deleteByKey

public void deleteByKey(K key) {}

说明:删除给定PK的实体。目前,仅支持惟一PK实体。

5.2.3 deleteByKeyInTx

public void deleteByKeyInTx(K... keys) {}

public void deleteByKeyInTx(Iterable<K> keys) {}

说明:使用事务删除数据库中给定键的所有实体。批量删除。

5.2.4 delete()

public void delete(T entity) {}

说明:删除给定的实体。目前,仅支持惟一PK实体。entity的id属性必须有值,否则报错。其实就是删除与entity主键值相同的数据,entity的其他数据值与表中数据值不一致时,也会删除。

5.2.5 deleteInTx()

public void deleteInTx(T... entities) {}

public void deleteInTx(Iterable<T> entities) {}

说明:使用事务删除数据库中给定的实体。批量删除。每个entity的id属性必须有值,否则报错。其实就是删除与entity主键值相同的数据,entity的其他数据值与表中数据值不一致时,也会删除。

5.3 改

5.3.1 update()

public void update(T entity) {}

说明:更新给定的实体。entity的id属性必须有值,否则报错。若entity的id值表中不存在时,不会报错。

5.3.2 updateInTx()

public void updateInTx(T... entities) {}

public void updateInTx(Iterable<T> entities) {}

说明:使用事务更新数据库中给定的实体。批量更新。每个entity的id属性必须有值,否则报错。若entity的id值表中不存在时,不会报错。

5.4 查

5.4.1 load()

public T load(K key) {}

说明:加载给定PK的实体。传入:key or null。返回:该实体 或 null。

5.4.2 loadByRowId()

public T loadByRowId(long rowId) {}

说明:加载给定RowId的实体。传入:key or null。返回:该实体 或 null。

5.4.3 loadAll()

public List<T> loadAll() {}

说明:从数据库加载所有可用的实体。

5.4.4 unique()

public T unique() {}

说明:返回一个或者零个结果。

5.4.5 uniqueOrThrow()

public T uniqueOrThrow() {}

说明:返回非空的结果,否则抛出异常。

5.5 其他

5.5.1 查看QueryBuilder拼接的SQL和参数信息

如果查询没有返回预期的结果,可以使用GreenDao提供的两个静态Flag打印QueryBuilder拼接的SQL和参数信息。

QueryBuilder.LOG_SQL = true;//打印SQL标志
QueryBuilder.LOG_VALUES = true;//打印参数标志

5.5.2 detach

5.5.2.1 detach()

public boolean detach(T entity) {}

说明:将一个实体从会话中拆分。后续查询结果不会返回此对象。

5.5.2.2 detachAll()

public void detachAll() {}

说明:将所有实体(T型)从身份范围(会话)中拆分。后续的查询结果不会返回任何以前加载的对象。

5.5.3 refresh()

public void refresh(T entity) {}

说明:通过从数据库重新加载重置该实体的所有本地更改属性。


六、高级查询

6.1 queryBuilder()

示例:

6.1.1 查询条件

  • between(Object value1, Object value2): BETWEEN … AND …
  • eq(Object value): equal (‘=’)
  • notEq(Object value): not equal (‘<>’)
  • gt(Object value): than (‘>’)
  • lt(Object value): less than (‘<’)
  • ge(Object value): greater or equal (‘>=’)
  • le(Object value): less or equal (‘<=’)
  • like(String value): LIKE
  • isNotNull(): IS NOT NULL
  • isNull(): IS NULL
  • in(Object… inValues): IN (…, …, …)
  • notIn(Object… notInValues): NOT IN (…, …, …)
  • in(Collection< ?> inValues): IN (…, …, …)
  • notIn(Collection< ?> notInValues): NOT IN (…, …, …)

6.1.2 Query的使用

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

示例:

public Query<T> setParameter(int index, String parameter) {}
public Query<T> setParameter(int index, Date parameter) {}
public Query<T> setParameter(int index, Boolean parameter) {}

说明:index 从 0 开始,代表where条件的下标;parameter代表需要修改的相应参数。

6.1.3 生成结果集方法

6.1.3.1 list()
public List<T> list() {}

说明:执行查询并将返回一个包含所有entity的list为结果,直接加载在内存中。

6.1.3.2 listLazy()
public LazyList<T> listLazy() {}

说明:用到懒加载技术。当真正用到数据时(访问entity的属性时),才会查询数据库。多用于多表级联查询。使用完必须关闭游标。

关闭游标:

6.1.3.3 listLazyUncached()
public LazyList<T> listLazyUncached() {}

说明:也实现了懒加载技术,但是返回结果list没有保存在内存中,没法复用,每次都会向数据库查询真正的数据。使用完必须关闭游标。

6.1.3.4 listIterator()
public CloseableListIterator<T> listIterator() {}

说明:执行查询并将结果作为列表迭代器返回;确保关闭它以关闭底层游标。一旦迭代器完全迭代,游标就会关闭。

6.2 原生SQL查询

如果GreenDao的查询条件不能满足,可以使用此方法定制自己的查询语句。

6.2.1 queryBuilder()

6.2.2 queryRawCreate()

public Query<T> queryRawCreate(String where, Object... selectionArg) {}

说明:基于给定的原始SQL创建一个可重复的{查询}对象,可以在这里传递任何WHERE子句和参数。

6.2.3 queryRaw()

public List<T> queryRaw(String where, String... selectionArg) {

说明:一个原始样式查询,可以在这里传递任何WHERE子句和参数。

6.2.4 queryRawCreateListArgs()

public Query<T> queryRawCreateListArgs(String where, Collection<Object> selectionArg) {}

说明:基于给定的原始SQL创建一个可重复的{查询}对象,您可以在这里传递任何WHERE子句和参数。

6.3 多线程查询

GreenDao多线程查询机制:每一个线程中都有一个查询对象,如果查询对象的创建线程和调用线程不一致,则抛出异常,通过这种机制来保证多线程查询的正确性。

示例:

注意:query.forCurrentThread()方法返回的Query对象的所有参数都会重置为QueryBuilder指定的初始值。在上述示例中指定初始值limit(3),然后更改为limit(5),query.forCurrentThread()方法会将所有参数重置为指定的初始值,所以为limit(3)。

运行结果:

6.4 1:1 查询

示例:现有两张表:作者表和文章表,文章表中有一列authorId对应作者表的id。希望可以通过文章的id查询作者信息。

作者表:

文章表:

查询id=1的文章的作者的信息:

查询结果:

6.5 1:N 查询

示例:现有两张表:作者表和文章表,文章表中有一列authorId对应作者表的id。希望可以通过作者id查询所有的文章信息。

6.5.1 实现方式一

作者表:

文章表:

查询id=1的作者的所有文章信息:

查询结果:

6.5.2 实现方式二

作者表:

文章表:

@ToMany()表明当前作者表的id对应章表的authorId。查询方式代码与方式一类似。


七、RxDao

导包:

compile 'io.reactivex:rxjava:1.3.0'
compile 'io.reactivex:rxandroid:1.2.1'

注意:目前仅支持RxJava1版本,不支持RxJava2版本。

DaoSession:

- RxTransaction    rx():返回在IO线程发射事件的 Observables
- RxTransaction    rxPlain():返回没有设置无线程调度的 Observables

Dao:

- RxDao<T, K>    rx()
- RxDao<T, K>    rxPlain()

QueryBuilder:

- RxQuery<T> rx()
- RxQuery<T> rxPlain()

备注:rxPlain形式没有设置调度线程,可根据需要自行指定工作线程。

7.1 Dao

7.1.1 初始化

7.1.2 增

注意:会把给定的实体在插入后发射给订阅者。(要插入的实体没有指定id(Entity设置了主键自增),返回实体有id,说明返回的是插入后的实体。其他方法类似。)

7.1.3 删

备注:其他方法(例如 save() )使用方式类似。

7.2 RxQuery

注意:此为异步线程,多处调用会导致每个线程开启事务,当其中一个线程关闭事务的时候其他线程不知道,导致死锁。


八、数据库加密

说明:

  • 使用getEncryptedReadableDb()和getEncryptedWritableDb()获取加密的数据库;
  • 256位AES加密,会提升APK的大小;
  • Robolectric(一种单元测试框架)测试时,须使用非加密数据库;

导包:

compile 'net.zetetic:android-database-sqlcipher:3.5.7@aar'

使用:

注意:必须使用相同的秘钥拿到Session才能将加密DB中的数据取出来,加密过的数据库文件使用工具打开也只能看到表结构,看不到表中的数据。


九、数据库版本迭代

DaoMaster.DevOpenHelper数据库升级时会删除所有表,仅适用于开发期。实际中需要继承DaoMaster.OpenHelper实现onUpgrade()方法。

@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {

    for (int j = oldVersion + 1; j <= newVersion; j++) {
        switch (j) {
            case 2:

                break;
            case 3:

                break;

            default:
                break;
        }
    }

}

升级辅助库 GreenDaoUpgradeHelper,通过 MigrationHelper 在删表重建的过程中,使用临时表保存数据并还原。gitHub地址,点击这里跳转

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值