关于GreenDao greenDao是一个将对象映射到SQLite数据库中的轻量且快速的ORM解决方案。
关于greenDAO的概念可以看官网greenDAO
greenDAO 优势
1、一个精简的库
2、性能最大化
3、内存开销最小化
4、易于使用的 APIs
5、对 Android 进行高
GreenDao 3.0使用
GreenDao 3.0采用注解的方式来定义实体类,通过gradle插件生成相应的代码。
一,在as中导入相关的包
compile’org.greenrobot:greendao:3.0.1’
compile’org.greenrobot:greendao-generator:3.0.0’
二,在build.gradle中进行配置:
apply plugin: ‘org.greenrobot.greendao’ buildscript {
repositories {
mavenCentral() } dependencies {
classpath ‘org.greenrobot:greendao-gradle-plugin:3.0.0’
} }
三,自定义路径
greendao {
schemaVersion 1
daoPackage ‘com.anye.greendao.gen’
targetGenDir ‘src/main/java’ }
**四,创建一个User的实体
@Entity
public class User {
@Id
private Long id;
private String name;
@Transient private int tempUsageCount;
// not persisted },MakeProject**
greenDao GreenDao使用 public class MyApplication extends Application {
private DaoMaster.DevOpenHelper mHelper; private SQLiteDatabase db;
private DaoMaster mDaoMaster; private DaoSession mDaoSession; public
static MyApplication instances; @Override public void onCreate() {
super.onCreate();
instances = this;
setDatabase(); } public static MyApplication getInstances(){
return instances; }/* 设置greenDao */ private void setDatabase() {
// 通过 DaoMaster 的内部类 DevOpenHelper,你可以得到一个便利的 SQLiteOpenHelper 对象。
// 可能你已经注意到了,你并不需要去编写「CREATE TABLE」这样的 SQL 语句,因为 greenDAO 已经帮你做了。
// 注意:默认的 DaoMaster.DevOpenHelper 会在数据库升级时,删除所有的表,意味着这将导致数据的丢失。
// 所以,在正式的项目中,你还应该做一层封装,来实现数据库的安全升级。
mHelper = new DaoMaster.DevOpenHelper(this, “notes-db”, null);
db = mHelper.getWritableDatabase();
// 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。
mDaoMaster = new DaoMaster(db);
mDaoSession = mDaoMaster.newSession(); }
public DaoSession getDaoSession() {
public SQLiteDatabase getDb() {
return db; } }
mUser = new User((long)2,”anye3”); mUserDao.insert(mUser);//添加一个
mUserDao.deleteByKey(id);
mUser = new User((long)2,”anye0803”); mUserDao.update(mUser);
List users = mUserDao.loadAll(); String userName = “”; for (int
i = 0; i < users.size(); i++) {
userName += users.get(i).getName()+”,”; }
mContext.setText(“查询全部数据==>”+userNam更多的操作就
不一一介绍了,大家可以根据需要去查找资料;greendao中的注解
(一) @Entity 定义实体
@nameInDb 在数据库中的名字,如不写则为实体中类名
@indexes 索引
@createInDb 是否创建表,默认为true,false时不创建
@schema 指定架构名称为实体
@active 无论是更新生成都刷新
(二) @Id
(三) @NotNull 不为null
(四) @Unique 唯一约束
(五) @ToMany 一对多
(六) @OrderBy 排序
(七) @ToOne 一对一
(八) @Transient 不存储在数据库中
(九) @generated 由greendao产生的构造函数或方法 快捷键
说明:所有的方法:
***AbstractDao
所有的自动生成的XXDao都是继承于AbstractDao,此类中基本上封装了所有的增删改操作,包括数据库的事务操作。常用的API如下:> void attachEntity(T entity):
long count():获取数据库中数据的数量
// 数据删除相关 void delete(T entity):从数据库中删除给定的实体 void
deleteAll() :删除数据库中全部数据
void deleteByKey(key):从数据库中删除给定Key所对应的实体
void deleteByKeyInTx(java.lang.Iterable keys):使用事务操作删除数据库中给定的所有key所对应的实体
void deleteByKeyInTx(K… keys):使用事务操作删除数据库中给定的所有key所对应的实体
void deleteInTx(java.lang.Iterable entities):使用事务操作删除数据库中给定实体集合中的实体
void deleteInTx(T… entities):使用事务操作删除数据库中给定的实体 // 数据插入相关
long insert(T entity):将给定的实体插入数据库
void insertInTx(java.lang.Iterable entities):使用事务操作,将给定的实体集合插入数据库
void insertInTx(java.lang.Iterable entities, boolean setPrimaryKey):使用事务操作,将给定的实体集合插入数据库,设置是否设定主键 void insertInTx(T… entities):将给定的实体插入数据库
long insertOrReplace(T entity):将给定的实体插入数据库,若此实体类存在,则覆盖
void insertOrReplaceInTx(java.lang.Iterableentities):使用事务操作,将给定的实体插入数据库,若此实体类存在,则覆盖
void insertOrReplaceInTx(java.lang.Iterable entities, boolean setPrimaryKey):使用事务操作,将给定的实体插入数据库,若此实体类存在,则覆盖设置是否设定主键
void insertOrReplaceInTx(T…entities):使用事务操作,将给定的实体插入数据库,若此实体类存在,则覆盖
long insertWithoutSettingPk(T entity):将给定的实体插入数据库,但不设定主键// 新增数据插入相关API
void save(T entity):将给定的实体插入数据库,若此实体类存在,则更新
void saveInTx(java.lang.Iterableentities):将给定的实体插入数据库,若此实体类存在,则更新
void saveInTx(T… entities):使用事务操作,将给定的实体插入数据库,若此实体类存在,则更新// 加载相关
T load(K key):加载给定主键的实体
java.util.List loadAll():加载数据库中所有的实体
protected java.util.List loadAllAndCloseCursor(android.database.Cursor cursor)
:从cursor中读取、返回实体的列表,并关闭该cursor
protected java.util.List loadAllFromCursor(android.database.Cursor cursor):从cursor中读取、返回实体的列表
T loadByRowId(long rowId) :加载某一行并返回该行的实体
protected T loadUnique(android.database.Cursor cursor) :从cursor中读取、返回唯一实体
protected T loadUniqueAndCloseCursor(android.database.Cursor cursor) :从cursor中读取、返回唯一实体,并关闭该cursor
//更新数据
void update(T entity) :更新给定的实体
protected void updateInsideSynchronized(T entity, DatabaseStatement stmt, boolean lock)
protected void updateInsideSynchronized(T entity, android.database.sqlite.SQLiteStatement stmt, boolean lock)
void updateInTx(java.lang.Iterable entities) :使用事务操作,更新给定的实体
void updateInTx(T... entities):使用事务操作,更新给定的实体
QueryBuilder、Query
基本查询
GreenDao中,使用QueryBuilder自定义查询实体,而不是再写繁琐的SQL语句,避免了SQL语句的出错率。大家都知道写SQL语句时,非常容易出错,出错后又十分的难查。QueryBuilder真是帮忙解决了一个大麻烦。具体该如何使用呢?
List joes = userDao.queryBuilder()
// 查询的条件
.where(Properties.FirstName.eq("Joe"))
// 返回实体集合升序排列
.orderAsc(Properties.LastName)
.list(); QueryBuilder qb = userDao.queryBuilder(); // 查询的条件 qb.where(Properties.FirstName.eq("Joe"), qb.or(Properties.YearOfBirth.gt(1970), qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10))));
List youngJoes = qb.list();
上面是官方给出的两个列子,不仅满足了查询语句的易写,同时使用了流式写法,提高了代码的可阅读性。 Limit、Offset、Pagination 在实际开发过程中,大家肯定碰到这样的问题,当数据过多在一页显示不出来的时候,要么选择前面十条显示,要么分页显示,但是数据总是获取全部的。其实,刚接触GreenDao的时候,也是这么干,获取全部的实体集合,然后再根据实际情况截取。看了API以后,豁然开朗,大神们已经帮我们解决了这件事。此时不得不说,QueryBuilder
中的Limit(限制)、Offset(偏移),limit(int)和offset(int)协同设置,可以完美解决分页显示。 [java]
view plain copy limit(int):限制查询返回结果的数目
offset(int):设置查询结果的偏移量,此查询需与limit(int)结合使用,而不能够脱离limit(int)单独使用
Query
当执行多次查询时,实际是QueryBuilder多次调用Query类。如果执行多次相同的查询,应使用QueryBuilder的build()方法来创建Query,而不是直接使用Query类。如果查询返回的结果是唯一性的,可以使用操作符方法,如果不希望此唯一性不返回
null,此时可调用uniqOrThrow()方法。如果查询返回的结果是多个,可以使返回的结果是一个集合,有如下方法: [java]
view plain copy list():所有实体加载至内存,结果通常是一个ArrayList
listLazy():实体在需要时,加载至内存,表中的第一个元素被第一次访问时会被缓存,下次访问时,使用缓存
listLazyUncached():任何对列表实体的访问懂事从数据库中加载
listIterator():以按需加载的方式来遍历结果,数据没有被缓存
一旦使用QueryBuilder创建了一个query,那么这个Query对象就可以就可以被复用来执行查询显然这种方式逼重新创建一次Query效率要高。
具体来说:[java] view plain copy 如果Query的参数没有变更,你只需要再次调用List/unuque方法即可
如果参数发生了变化,那么就需要通过setParameter方法来处理每一个发生改变的参数
举例: [java] view plain copy Query query = userDao.queryBuilder().where(Properties.FirstName.eq(“Joe”),
Properties.YearOfBirth.eq(1970)).build(); List joesOf1970 =
query.list();现在复用该Query对象:
[java] view plain copy query.setParameter(0, “Maria”);
query.setParameter(1, 1977); List mariasOf1977 = query.list();由此可见,Query在执行一次build之后会将查询结果进行缓存,方便下次继续使用。 执行原生SQL语句 两种方法:
[java] view plain copy Query query = userDao.queryBuilder().where(
new StringCondition(“_ID IN ” + “(SELECT USER_ID FROM USER_MESSAGE
WHERE READ_FLAG = 0)”).build();
如果这里的QueryBuilder没有提供你想要的特性,可以使用原始的queryRaw或queryRawCreate方法。[java] view plain copy Query query = userDao.queryRawCreate( “, GROUP
G WHERE G.NAME=? AND T.GROUP_ID=G._ID”, “admin”);
注:写SQL语句时推荐定义常量来表示表名或者表项,这样可以防止出错,因为编译器会检查
六、数据库加密
在Greendao的迭代流程中可以看到这么一个库
1 compile ‘org.greenrobot:greendao-generator-encryption:3.0.0beta3’
Greendao3
与下面这个加密库合作,encryption:3.0.0beta-3相当于一个适配层,之后迭代中并入greendao主库的3.0.1版本,对database相关的api进行了统一。1 compile ‘net.zetetic:android-database-sqlcipher:3.5.2’
之前的版本也是支持加密的,但是可以理解为在相互api传递数据的时候面临各种类型转换,3.0将其统一,使用更加流畅。
User man1 = new User(); man1.setId(10001); man1.setName(“kobe”);
DaoMaster.DevOpenHelper a = new
DaoMaster.DevOpenHelper(this,”database_name”,null); try {
daoSession = new DaoMaster(a.getEncryptedWritableDb(MY_PWD)).newSession();
daoSession.getUserDao().insert(man1); }catch (Exception e){
Log.d(“e”, String.valueOf(e)); }
DaoSession normalSession = new
DaoMaster(a.getWritableDb()).newSession();
Log.d(“无法取数据”,normalSession.getUserDao().loadAll().toString());
DaoSession encryptedSession = new
DaoMaster(a.getEncryptedWritableDb(MY_PWD)).newSession();//董铂然 博客园
Log.d(“可以取数据”,encryptedSession.getUserDao().loadAll().toString());
07-27 /com.XXX.dsx.testgreendao3 D/无法取数据: [] 07-27
/com.XXX.dsx.testgreendao3 D/可以取数据:
[com.XXX.dsx.testgreendao3.User@2ae5190]
如果把加密后的数据库的本地文件扒出来,也是查不到内容的, 使用dump仅仅可以看到表结构和列名。
如果觉得还不满意,可以对列名再进行加密。在建表时就对列名加密,后续使用可能会比较麻烦,建议加密一些关键表如USER,ACCOUNT。
七:数据库迁移
allprojects { repositories { … maven { url
“https://jitpack.io” } } }
2.添加依赖(greendao 3.0及以上)
dependencies {
compile 'org.greenrobot:greendao:3.2.0'
compile 'com.github.yuweiguocn:GreenDaoUpgradeHelper:v2.0.0'
}
如果你使用的greendao是3.0以前的版本,请使用下面的依赖:
dependencies {
compile 'de.greenrobot:greendao:2.0.0'
compile 'com.github.yuweiguocn:GreenDaoUpgradeHelper:v1.0.1'
}
3.添加一个新类继承DaoMaster.OpenHelper,添加构造函数并实现onUpgrade方法,在onUpgrade方法添加如下代码即可,参数为所有的Dao类:
MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {
@Override
public void onCreateAllTables(Database db, boolean ifNotExists) {
DaoMaster.createAllTables(db, ifNotExists);
}
@Override
public void onDropAllTables(Database db, boolean ifExists) {
DaoMaster.dropAllTables(db, ifExists);
}
},TestDataDao.class, TestData2Dao.class, TestData3Dao.class);
完整代码:
public class MySQLiteOpenHelper extends DaoMaster.OpenHelper {
public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {
@Override
public void onCreateAllTables(Database db, boolean ifNotExists) {
DaoMaster.createAllTables(db, ifNotExists);
}
@Override
public void onDropAllTables(Database db, boolean ifExists) {
DaoMaster.dropAllTables(db, ifExists);
}
},TestDataDao.class, TestData2Dao.class, TestData3Dao.class);
}
}
4.初始化
//MigrationHelper.DEBUG = true; //如果你想查看日志信息,请将DEBUG设置为true
MySQLiteOpenHelper helper = new MySQLiteOpenHelper(this, “test.db”,
null);
daoMaster = new DaoMaster(helper.getWritableDatabase());
也可以去链接这篇链接:https://github.com/yuweiguocn/GreenDaoUpgradeHelper/blob/master/README_CH.md
参考文章:
http://blog.csdn.net/njweiyukun/article/details/51893092
http://blog.csdn.net/njweiyukun/article/details/51893092
http://www.jianshu.com/p/793f77feeb89
http://www.cnblogs.com/dsxniubility/archive/2016/07/28/5699543.html
http://blog.csdn.net/io_field/article/details/52214099
http://blog.csdn.net/ddk837239693/article/details/53516298
https://www.daidingkang.cc/2016/12/08/GreenDao/#more