greenDAO的使用总结
1、简述
图片来自greenDAO官网
greenDAO是由greenRobot(大名鼎鼎的EventBus也是出自他们家)出品的一个ORM(对象关系映射)的SQlite数据库操作框架。其利于注解和JavaBean,可以直接生成一个类相对应的数据表。并可以自动生成对该表操作的对应DAO类。除此之外,greenDAO很好的支持了数据库升级,以及sqlcipher数据库加密。通过greenDAO,我们可以更方便的操作数据库。
本文以greenDAO3.0.1为例,介绍一下greenDAO的使用。
2、在项目中集成greenDAO
(1)首先在整个项目的gradle中添加如下代码:
buildscript {
repositories {
jcenter()
mavenCentral() // add repository
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'
classpath 'org.greenrobot:greendao-gradle-plugin:3.0.0'// add plugin
}
}
(2)在app的Gradle中添加:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
greendao {
//greenDAO操作的数据库版本号,用于升级数据库用
schemaVersion 1
//自己指定,自动生成的DAO类所存储的文件夹名称
daoPackage 'com.xxx.xxx.greendaodemo.greendao'
targetGenDir 'src/main/java'
}
dependencies {
compile 'org.greenrobot:greendao:3.0.1'
compile 'org.greenrobot:greendao-generator:3.0.0'
compile 'net.zetetic:android-database-sqlcipher:3.5.2'
}
注意:schemaVersion必须大于等于1。否则报错:
java.lang.IllegalArgumentException: Version must be >= 1, was 0
因为在SQLiteOpenHelper中有如下代码:
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
DatabaseErrorHandler errorHandler) {
if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
mContext = context;
mName = name;
mFactory = factory;
mNewVersion = version;
mErrorHandler = errorHandler;
}
3、注解类
接下来,我们需要创建一个JavaBean类,并使用greenDAO的注解来帮忙生成相应的DAO类。主要其实是介绍greenDAO下几个常用注解的使用。
(1)Entity注解
用于类之上,表示该类会被greenDAO映射为一个表。默认使用的表名即是类名。
例如我们这里有一个People类使用Entity如下:
@Entity
public class People {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
那么我们在程序跑起来后,去查看一下People表。如下:
当然,你也可以自己指定表名。通过nameInDb字段指定即可,还是之前的People类,我们把表名指定为PeopleTable试一下(注意这里涉及到数据库升级,下一篇会介绍)。如下:
@Entity(nameInDb = "PeopleTable")
public class People {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
再查看下之后生成的表:
这里我们就可以看到PeopleTable表了。
(2)Id
用Id注解的字段,会作为主键,其自带自增属性。主键类型最好使用Long包装类型,不要使用long数据类型。否则在插入多条数据时可能会引起程序崩溃。
报如下错误:
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: PeopleTable._id
示例如下:
@Id
private Long autoId;
生成的表中会有如下字段:
这就是生成的主键字段名。这个字段名是由于其作为主键,GreenDao统一给定的字段名,即_id。
很明显这不是我们想要的字段名,我们希望这里可以与变量名一致,即autoId。那么该如何做呢?看下面一个注解。
(3)Property
其实这里我们还是需要通过nameInDb来重新设置。只是之前的Entity是注解类的。我们这里就需要Property注解来对变量进行注解。
如下:
@Property(nameInDb = "autoId")
@Id
private Long autoId;
我们来看一下效果:
(4)Transient
有时候我们的类中可能会有些内容我们不想让他们被加入到表中。比如我在Person类中有两个常量:
public static final String SEX_MAN = "Man";
public static final String SEX_WOMAN = "Woman";
我不做任何处理,直接跑程序。由于greenDAO会自动为类中的字段添加getter和setter方法。于是就出现了如下这种问题情况:
报错:
你个常量你是不能给他重新赋值的。于是这就需要Transient注解了。添加了该注解就不会生成表中的列,不会将该变量持久化,greenDAO也不会自动为他生成getter和setter方法了。
(5)Unique
使用这个注解可以为相应变量的列添加唯一性约束。比如我们的程序中经常有用户表。而UserId一定是唯一的。我们就可以为UserId添加一下这个注解。
4、操作数据库前要做的事
有了要操作的实体类。接下来我们就希望通过greenDAO把他映射到数据库,进而进行增删改查操作了。但别急,我们先得做一下几个事情。
(1)创建一个数据库的OpenHelper。
示例如下:
DaoMaster.DevOpenHelper mDevOpenHelper = new DaoMaster.DevOpenHelper(
mContext,
"GreenDaoDb",
null
);
这里主要是通过OpenHelper来指定你要操作哪一个数据库。greenDAO的OpenHelper有2个:DevOpenHelper,OpenHelper。
注意,greenDAO特别对DevOpenHelper做了如下说明:
WARNING:Drops all table on Upgrade!Use only during development.
DevOpenHelper会在升级时删除所有的表,因此建议只在开发时使用它。
这是什么意思呢?我们来看一下OpenHelper和DevOpenHelper的源码就知道了:
/**
* Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} -
*/
public static abstract class OpenHelper extends DatabaseOpenHelper {
public OpenHelper(Context context, String name) {
super(context, name, SCHEMA_VERSION);
}
public OpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory, SCHEMA_VERSION);
}
@Override
public void onCreate(Database db) {
Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
createAllTables(db, false);
}
}
/** 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) {
dropAllTables(db, true);
onCreate(db);
}
}
可以看到DevOpenHelper实际是继承于OpenHelper的,它覆盖了OpenHelper中的一个方法onUpgrade。使用过原生数据库的朋友们对这个方法应该不陌生。这个方法是在数据库升级时调用。DevOpenHelper在该方法中调用了dropAllTables方法删除了所有的表。之后又通过onCreate方法,onCreate方法中调用createAllTables创建了所有的表。
(2)通过这个OpenHelper获取到一个SQLiteDatabase对象。
示例如下:
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
greenDAO中提供了4种方法来获取SQLiteDatabase对象,分别是getReadableDatabase(获取一个可读数据库);getWriteableDatabase(获取一个可写数据库);getEncryptedReadableDb(获取一个加密可读数据库);getEncryptedWriteableDatabase(获取一个加密可写数据库)。
关于加密这一块,会在本文后面一块中说明。
(3)创建一个DaoMaster对象,并将SQLiteDatabase对象传入。
示例:
DaoMaster daoMaster = new DaoMaster(db);
DaoMaster是greenDAO使用的入口。其代表一个数据库连接,并管理着这个数据库、版本、与该数据库有关的DAO类。
(4)通过DaoMaster对象获取到DaoSession对象。
示例:
DaoSession daoSession = daoMaster.newSession();
DaoSession管理着DAO对象,用于获取DAO对象,进而对数据库中的相应表进行操作。DaoSession可以建立多个,但每个都属于同一个数据库连接。
5、增删改查
上面最后一步,我们获取到了DaoSession对象。我们可以通过DaoSession对象获取DAO类的实体对象了。
DAO类是干嘛的呢?DAO类由greenDAO对于Entity类自动生成,封装了相应的增删改查方法。换句话说,我们就是依赖DAO类对ORM后的数据表进行增删改查的。
对于增删改查操作,我们这里只列举几个常见的api。其余的可以自己去查看greenDAO的api文档来使用,这一块并不难。
(1)增
People people = new People();
Random random = new Random();
people.setName(
"姓名-"+ random.nextInt(10000)
);
daoSession.getPeopleDao().insert(
people
);
(2)删
根据主键删除某一个元素:
daoSession.getPeopleDao().deleteByKey(1L);
删除所有元素:
daoSession.getPeopleDao().deleteAll();
(3)改
People people = new People();
Random random = new Random();
people.setName(
"姓名-"+ random.nextInt(10000)
);
people.setAutoId(1);
daoSession.getPeopleDao().update(people);
(4)查
List<People> peopleList = daoSession
.getPeopleDao()
.queryBuilder()
.orderDesc(PeopleDao.Properties.AutoId)
.where(PeopleDao.Properties.AutoId.eq(1))
.build()
.list();
6、数据库加密
之前我们提到过,方法getEncryptedReadableDb(获取一个加密可读数据库);getEncryptedWriteableDatabase(获取一个加密可写数据库)。这两个方法的不同之处就在于参数中需要多传入一个key,这个key的内容由你自己指定。可以认为是一个加密密码。同样的增删改查都需要依赖于这个加密的Database对象来操作。其内部是基于SQLCipher对数据库进行加密的。
另外注意,要使用这两个方法必须引入加密依赖库:
compile 'net.zetetic:android-database-sqlcipher:3.5.2'
否则会报如下错误:
java.lang.NoClassDefFoundError: org.greenrobot.greendao.database.DatabaseOpenHelper$EncryptedHelper
示例:
public Database getEncryptedWritableDatabase() {
if (mOpenHelper == null) {
mOpenHelper = new DaoMaster.DevOpenHelper(
mContext,
DBController.getDBName(mContext),
null
);
}
Database db = mOpenHelper.getEncryptedWritableDb("EncryptedDbKey");
return db;
}
如果我们使用了加密数据库插入一个数据,那么就无法预览到成功插入后的数据了,如下:
现在你什么也预览不到了。
篇幅有限,本篇先介绍到这里。