Android ORM 框架 GreenDAO 3 基本使用方法

最近刚刚接触 Android ORM 框架 GreenDAO 3,现在记录一下学习过程。

GreenDAO 的官网配置步骤依赖 maven,但是如果不加任何设置直接访问 maven 官方仓库速度奇慢无比,有时候甚至 30 分钟都无法成功连接。好在之前阿里云悄悄咪咪的上线了 maven 仓库镜像,普遍反应国内访问速度不错,现在就来配置 maven 的阿里云镜像。

  1. 首先在 File -> Settings 菜单中,找到 maven 设置:Build, Execution, Deployment -> Build Tools -> maven
  2. 在 User settings file 一项为用户的自定义设置文件位置,勾选右边的 Override 单选框
    maven.PNG

一般只要没有过任何改动这里的设置路径都是默认的 C:\Users\<用户名>\.m2\settings.xml,也可以自定义自己的路径。

  1. 之后编写自己的 maven 配置文件,可以直接复制 Intellij 自带的 maven 插件配置文件,位置一般在 C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.3\plugins\maven\lib\maven3\conf\settings.xml (如果是其他 Intellij 版本,则找到对应版本的文件即可)
  2. 找到配置文件的 mirrors 标签,在其中添加阿里云的镜像配置信息,具体代码为:
1
2
3
4
5
6
<mirror>
    <id>alimaven</id>  
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>
</mirror>

idname 可以随自己喜欢设置

  1. app 的 build.gradle 文件 中加入
1
apply plugin: 'org.greenrobot.greendao'
  1. app 的 build.gradle 文件dependencies 项中加入
1
compile 'org.greenrobot:greendao:3.2.0'

版本号参考官网文档

  1. 继续在 app 的 build.gradle 文件 中加入
1
2
3
4
5
6
7
8
9
buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'
    }
}

注意:如果需要设置项目所有模块都使用 GreenDAO,则应在 项目的 build.gradle 文件 加入以上代码

而后,sync gradle 配置文件即可。

app 的 build.gradle 文件 中设置 greenDAO Gradle plugin 的信息,加入如下代码:

1
2
3
4
5
greendao {
    schemaVersion 1
    daoPackage 'com.example.android.gen'
    targetGenDir 'src/main/java'
}

实际上,不加任何设置也是没有问题的,但是加上设置可以更好的自定义 GreenDAO 的工作方式:

  • schemaVersion:数据库版本号,升级使用,不设置时默认为 1
  • daoPackage:生成的代码文件的包名,默认和模型类相同
  • targetGenDir:生成的代码文件的位置,默认在 build/generated/source/greendao

其他更多配置可参考官方文档的 Schema 部分

模型类只需要基本的成员变量即可,其余代码会由 GreenDAO 库生成。GreenDAO 使用 APT 分析和生成代码,只要对模型类标注特定的注解即可,比如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Entity
public class Book {

    @Id(autoincrement = true)
    private Long id;

    private String author;

    private double price;

    private int pages;

    @NotNull
    private String name;

    private String press;
}

常用的注解有:

  • Entity:标记类为数据模型类

  • Id:标记成员为表的 id 列

    必须为 long 或者 Long 类型,默认是没有自增属性,如果要设置自增,增需使用 @Id(autoincrement = true),且必须为 Long 类型

  • NotNull:标记数据表的此列不能为空

  • Unique:表明数据表的此列要符合 unique 约束

默认情况下,累的成员变量对应数据表的列,而且变量名对应列名,如果想要令列名不同则使用 @Property(nameInDb = "xxx") 命名对应的列。 其他更多的注解使用可以参考官方文档的 Entities and Annotations 部分

最后,在编写好模型类之后执行 bulid 命令即可自动生成需要的代码,本文中生成了 BookDaoDaoMasterDaoSession,同时还在 Book 中生成了相应的 getter 和 setter。

CRUD 操作需要借助相应的 Dao 类实例进行,而 Dao 需通过 DaoSession 获取,DaoSession 则通过 DaoMaster 获取,而之后就需要构建需要的 Book 实例来实现 CRUD 操作,比如常用的数据库管理器代码可以如下编写:

 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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
public DBManager{

    private static final String DATABASE_NAME = "BookStore";

    private static DBManager sInstance;

    private DaoMaster.OpenHelper mOpenHelper;

    private Context mContext;

    private DBManager(Context context) {
        mContext = context;
        mOpenHelper = new MySQLiteOpenHelper(context, DATABASE_NAME, null);
    }

    public static DBManager getInstance(Context context) {
        if (sInstance == null) {
            synchronized (DBManager.class) {
                if (sInstance == null) {
                    sInstance = new DBManager(context);
                }
            }
        }
        return sInstance;
    }

    private SQLiteDatabase getReadableDatabase() {
        if (mOpenHelper == null) {
            mOpenHelper = new MySQLiteOpenHelper(mContext, DATABASE_NAME, null);
        }
        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        return db;
    }

    private SQLiteDatabase getWritableDatabase() {
        if (mOpenHelper == null) {
            mOpenHelper = new DaoMaster.DevOpenHelper(mContext, DATABASE_NAME, null);
        }
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        return db;
    }

    private BookDao getWritableBookDao() {
        DaoMaster daoMaster = new DaoMaster(getWritableDatabase());
        DaoSession daoSession = daoMaster.newSession();
        return daoSession.getBookDao();
    }

    private BookDao getReadableBookDao() {
        DaoMaster daoMaster = new DaoMaster(getReadableDatabase());
        DaoSession daoSession = daoMaster.newSession();
        return daoSession.getBookDao();
    }

    // 增加一本书籍
    public void insertBook(Book book) {
        getWritableBookDao().insert(book);
    }

    // 增加多本书籍
    public void insertBooks(List<Book> books) {
        if (books == null || books.isEmpty()) {
            return;
        }
        getWritableBookDao().insertInTx(books);
    }

    // 删除一本书籍
    public void deleteBook(Book book) {
        getWritableBookDao().delete(book);
    }

    // 更新一本书籍
    public void updateBook(Book book) {
        getWritableBookDao().update(book);
    }

    // 获取所有书籍信息
    public List<Book> queryAllBooks() {
        return getWritableBookDao().loadAll();
    }

    // 清空数据表 Book
    public void deleteAllBooks() {
        getWritableBookDao().deleteAll();
    }
}

特比注意的是,这其中获取 Dao 的代码分两种情况 getWritableBookDao()getReadableBookDao(),对应读和写。 当然,删除和更新的操作需要注意 id 是否自增,应该先查找在修改,这里就不再演示了。

如果需要更复杂的 SQL 语句操作,则可以使用 QueryBuilder,其说明文档为:http://greenrobot.org/greendao/documentation/queries/

GreenDao 数据库升级代码位于 DaoMaster 中,默认会删除所有数据,而后重新生成新的数据库文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    /** WARNING: Drops all table on Upgrade! Use only during development. */
    public static class DevOpenHelper extends OpenHelper {
        public DevOpenHelper(Context context, String name) {
            super(context, name);
        }

        public DevOpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory);
        }

        @Override
        public void onUpgrade(Database db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
            dropAllTables(db, true);
            onCreate(db);
        }
    }

当然,可以自定义升级的方法,通过复制数据到新的数据表来保存已有数据,不过,总的来说还是稍显麻烦,不如直接使用已有的开源库 GreenDaoUpgradeHelper

  1. 项目的 build.gradle 文件 中找到 allprojects 项,修改为如下样子:
1
2
3
4
5
6
allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}
  1. app 的 build.gradle 文件dependencies 项中加入
1
compile 'com.github.yuweiguocn:GreenDaoUpgradeHelper:v1.3.0'
  1. 新建一个 DaoMaster.OpenHelper 的子类,在其中设置升级方法 onUpgrade
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.example.android.databasetest;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.github.yuweiguocn.library.greendao.MigrationHelper;

public class MySQLiteOpenHelper extends DaoMaster.OpenHelper{

    public MySQLiteOpenHelper(Context context, String name) {
        super(context, name);
    }

    public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        MigrationHelper.migrate(db, BookDao.class);
    }
}
  1. 修改 DBManager 的代码中的构造方法 DaoMaster.DevOpenHelperMySQLiteOpenHelper
  2. 进行数据库升级操作,如果修改 Book 代码需要 GreenDAO 生成新的代码,应在 Book 修改后执行 bulid 命令
  3. 修改 app 的 build.gradle 文件 中 greenDAO Gradle plugin 的设置信息,将 schemaVersion 改为 2
  4. 重新 build 项目

参考: http://greenrobot.org/greendao/documentation/ http://blog.csdn.net/Hi_AndG/article/details/54729433