马上过年了,近期不是很忙,总结一篇关于GreenDao的详解文章
greenDAO增删改查在不同情况下的应用,以及模拟离线和线上的数据存储
结尾附有Demo以及下载地址
greenDAO is an open source library for Android providing an easy-to-use interface to SQLite to help developers handle data efficiently – relieving developers from dealing with low-level database stuff and saving development time. SQLite is an awesome embedded relational database. Still, writing SQL and parsing query results are quite tedious and time-consuming tasks. greenDAO frees you from these by mapping Java objects to database tables (often called ORM). This way you can store, update, delete, and query for Java objects using a simple object oriented API.
————————————————
greenDAO是一款开放源代码的Android ORM,使SQLite数据库的开发变得有趣。它减轻开发人员处理低级数据库需求,同时节省开发时间。SQLite是一个令人敬畏的嵌入式关系数据库。不过,编写SQL和解析查询结果是相当乏味和耗时的任务。通过将Java对象映射到数据库表(称为ORM “对象/关系映射”),greenDAO可以将它们从这些映射释放出来。这样,您可以使用简单的面向对象的API来存储,更新,删除和查询Java对象。
apply plugin: 'org.greenrobot.greendao'
android {
greendao {
schemaVersion 1//数据库版本号
daoPackage 'com.harry.greendaomaster.greendao.gen'//设置DaoMaster、DaoSession、Dao包名
targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录
//targetGenDirTest:设置生成单元测试目录
//generateTests:设置自动生成单元测试用例
}
}
dependencies {
//GreenDao
implementation 'org.greenrobot:greendao:3.2.2'
}
// 在 Project的build.gradle 文件中添加:
buildscript {
repositories {
mavenCentral() // add repository
}
dependencies {
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
}
}
/**
* @author 拉莫帅
* @date 2022/1/5
* @address
* @Desc 全局初始化
*/
public class MyApp extends Application {
private DaoSession mDaoSession;
public static MyApp instances;
public static Context context;
@Override
public void onCreate() {
super.onCreate();
instances = this;
context = getApplicationContext();
setDatabase();
}
public static MyApp getInstances() {
return instances;
}
public static Context getAppContext() {
return context;
}
/**
* 设置greenDao
*/
private void setDatabase() {
DaoMaster.DevOpenHelper mHelper = new DaoMaster.DevOpenHelper(this, "harry-db", null);
SQLiteDatabase db = mHelper.getWritableDatabase();
DaoMaster mDaoMaster = new DaoMaster(db);
mDaoSession = mDaoMaster.newSession();
}
public DaoSession getDaoSession() {
return mDaoSession;
}
}
/**
* @author 拉莫帅
* @date 2022/1/5
* @address
* @Desc 人物
*
* 创建数据库实体类
*
* @Entity 表示这个实体类一会会在数据库中生成对应的表
*
* @Id 表示该字段是id,注意该字段的数据类型为包装类型Long
*
* @Property 则表示该属性将作为表的一个字段,其中nameInDb看名字就知道这个属性在数据库中对应的数据名称
*
* @Transient 该注解表示这个属性将不会作为数据表中的一个字段
*
* @NotNull 表示该字段不可以为空
*
* @Unique 表示该字段唯一
*/
@Override
protected void initData() {
/**
* 初始化数据库
*/
DaoSession daoSession = MyApp.getInstances().getDaoSession();
userDao = daoSession.getUserDao();
}
/**
* <条件删除>
* 根据ID删除单条数据
* 条件删除>
*/
long l = userDao.count() - 1;
userDao.deleteByKey(l);
/**
* <条件删除>
* 用户名 Username
* 单个条件删除 eq
* 条件删除>
*/
userDao.queryBuilder()
.where(
UserDao.Properties.Username.eq(name)
).buildDelete()
.executeDeleteWithoutDetachingEntities();
/**
* <条件删除>
* 用户名 Username
* 密码 Password
* 多条件删除 eq
* 条件删除>
*/
userDao.queryBuilder()
.where(
UserDao.Properties.Username.eq(name),
UserDao.Properties.Password.eq(passWord)
).buildDelete()
.executeDeleteWithoutDetachingEntities();
/**
* 删除全部数据
*/
userDao.deleteAll();
@Unique
unique
属性,在GreenDao创建数据库表时会自动为此字段创建唯一索引解决方法:
(1)我们需要捕获异常并忽略。
try {
dao.insert(user);
} catch (SQLiteConstraintException e) {
// 主键或unique唯一索引冲突,忽略
Log.e("数据去重 >>", "数据重复,忽略");
}
(2)把insert
替换为insertOrReplace
。
(3)查询后插入,在插入之前先查询是否已存在,存在则不插入,从而达到去重效果。
User queryUser = dao.queryBuilder().where(UserDao.Properties.Name.eq("张三")).unique();
if (queryUser == null) {
dao.insert(user);
} else {
Log.d(TAG, "数据重复,忽略");
}
(4)插入后删除重复,先将所有数据插入,然后通过查询找出重复数据并删除。
dao.insert(user);
List<User> repeatUsers = dao.queryBuilder().where(UserDao.Properties.Name.eq("张三")).list();
if (repeatUsers.size() > 1) {
dao.delete(repeatUsers.get(1)); // 删除第二条重复数据
}
在使用修改的操作的时候,这里总结了一个使用时候的bug
对单条数据进行修改的话,是不会出现问题的
但是如果出现多条重名的数据,进行修改的话,会报一个错,如下:
/**
* <条件修改>
* 用户名 Username
* 修改单条用户数据 eq
* </条件修改>
*/
User user = userDao.queryBuilder()
.where(
UserDao.Properties.Username.eq(name)
).build()
.unique();
Toast.makeText(MainActivity.this, "" + name, Toast.LENGTH_SHORT).show();
if (user != null) {
user.setUsername(updateMsg);
userDao.update(user);
}
这时候就不能用unique了,修改为list,就可以解决以上问题,修改如下:
/**
* <条件修改>
* 用户名 Username
* 修改多条用户重复数据 eq
* </条件修改>
*/
List<User> list = userDao.queryBuilder()
.where(
UserDao.Properties.Username.eq(name)
).build()
.list();
Log.e("数据", "updateUser: " + list.size());
if (list.size() > 0) {
for (int i = 0; i < list.size(); i++) {
list.get(i).setUsername(updateMsg);
userDao.update(list.get(i));
}
}
QueryBuilder的使用
QueryBuilder的常见方法: where(WhereCondition cond, WhereCondition…
condMore): 查询条件,参数为查询的条件! or(WhereCondition cond1, WhereCondition
cond2, WhereCondition… condMore): 嵌套条件或者,用法同or。 and(WhereCondition
cond1, WhereCondition cond2, WhereCondition… condMore):
嵌套条件且,用法同and。 join(Property sourceProperty, Class
destinationEntityClass):多表查询
输出结果有四种方式,选择其中一种最适合的即可,list()返回值是List,而其他三种返回值均实现Closeable,需要注意的不使用数据时游标的关闭操作:
list ()所有实体都加载到内存中。结果通常是一个没有魔法的 ArrayList。最容易使用。 listLazy
()实体按需加载到内存中。首次访问列表中的元素后,将加载并缓存该元素以供将来使用。必须关闭。 listLazyUncached
()实体的“虚拟”列表:对列表元素的任何访问都会导致从数据库加载其数据。必须关闭。 listIterator
()让我们通过按需加载数据(懒惰)来迭代结果。数据未缓存。必须关闭。 orderAsc() 按某个属性升序排; orderDesc()
按某个属性降序排;
GreenDao中SQL语句的缩写,我们也了解下,源码在Property中,使用的时候可以自己点进去查询即可:
eq():"equal ('=?')" 等于;
notEq() :"not equal ('<>?')" 不等于;
like():" LIKE ?" 值等于;
between():" BETWEEN ? AND ?" 取中间范围;
in():" IN (" in命令;
notIn():" NOTIN (" not in 命令;
gt():">?" 大于;
lt():" " 小于;
ge():">=?" 大于等于;
le():"<=? " 小于等于;
isNull():" IS NULL" 为空;
isNotNull():" IS NOT NULL" 不为空;
/**
* 查询全部用户数据
*/
List<User> list = userDao.loadAll();
/**
* <条件查询>
* 用户名 Username
* 模糊查询 like
* 条件查询>
*/
List<User> list = userDao.queryBuilder()
.where(
UserDao.Properties.Username.like("%" + name + "%")
).build()
.list();
/**
* <条件查询>
* 用户名 Username
* 密码 Password
* 多条件查询 eq
* 条件查询>
*/
List<User> list = userDao.queryBuilder()
.where(
UserDao.Properties.Username.eq(name),
UserDao.Properties.Password.eq(pwd)
).build()
.list();
/**
* <条件查询>
* 用户名 Username
* 单条件查询 eq
* 条件查询>
*/
List<User> list = userDao.queryBuilder()
.where(
UserDao.Properties.Username.eq(name)
).build()
.list();
/**
* <条件查询>
* 自增ID
* orderAsc 以字段升序排序
* orderDesc 以字段降序
* 条件查询>
*/
List<User> list = userDao.queryBuilder()
.orderAsc(UserDao.Properties.Id)
.build()
.list();
项目下载地址:GreenDaoMaster