大致分为以下几个方面:

  1. 一些查询指令整理
  2. 使用SQL语句进行特殊查询
  3. 检测表字段是否存在
  4. 数据库升级
  5. 数据库表字段赋初始值

一、查询指令整理

1.链式执行的指令

return mDaoSession.getUserDao().queryBuilder().
XXX.
XXX.
XXX.
list();

一般的查询语句会在中间xxx的位置加上各种判断和过滤的方法指令,除了最后的终结指令list()或unique()返回的是集合或业务对象,其他的都是返回QueryBuilder对象,大多数情况下XXX的位置都是填上where语句,还有一些其他和sql关联的语句便于使用。

“whereOr” where语句里面写的条件都是用“且”连接,whereOr里的语句使用“或”连接

“distinct”  直接过滤掉重负字段

“limit”  分页n个一页,一般和offset结合使用

“offset” 忽略查询出的前n条结果

“orderAsc” 以字段升序排序

“orderDesc”以字段降序

“preferLocalizedStringOrder” 本地化字符串排序

“orderCustom” 自定义排序 里面需要传两个参数: 一个属性 和对应的排序方案 ASC 或是 DESC

“orderRaw”  也是自定义排序, 把字段和 排序方案 写在一个字符串传入

“stringOrderCollation” 也是自定义排序 可以合并多个升降排序方案 以日期升序 且 价格降序

2.条件里的指令

return mDaoSession.getUserDao().queryBuilder().
where(UserDao.Properties.UserId.in(userIdList), UserDao.Properties.UserAge.eq(19)).
list();

一个简单的where语句大概是这样,在where的括号里面可以并列的写很多条件,其中全部以“且” 来连接。除了上面的“in”和“eq”还有很多其他判断条件

“notEq” 和eq相反,别傻傻在再去外面敲“!”取反

“notIn” 同上

“or” 或者

“like” 就是sql语句的LIKE  "%"+string+"%"

“between” 也就是BETWEEN ? AND ?  可以取两个值的区间 (但是这条语句要慎用,不同的数据库不一样,有的是A<条件<B,有的是A<=条件<=B)

“gt” 相当于 >

“ge”相当于 >=

“lt” 相当于 <

“le”相当于  <=

“isNull” 为空

“notIsNull” 不为空

二、使用SQL语句进行特殊查询

一般遇到普通的增删改查操作无法轻易实现的功能,会使用这种rawQuery的方式。 我经常遇到的也就是两种场景:

1.使用SELECT DISTINCT

常用与一对多关系,假设图书馆现在有个“用户存书表” 有的用户有20本书,表里就会有20条他的数据,每条对应一本不同的书。

这时假设有个需求,查出这个表中,所有的用户名字,不许重复。 这时候用普通的查询指令就会非常麻烦了,需要使用SELECT DISTINCT指令查出某列名所有不重复的条目。

String queryString =
"SELECT DISTINCT " + UserBookDao.Properties.UserName.columnName + " FROM " + UserBookDao.TABLENAME
+ " ORDER BY "
+ UserBookDao.Properties.CreatedTime
+ " DESC "
+ " LIMIT "
+ page * LIMIT_NUM
+ " , "
+ LIMIT_NUM; ArrayList<String> result = new ArrayList<>();
Cursor c = mDaoSession.getDatabase().rawQuery(queryString,new String[]{});
try {
if (c != null) {
if (c.moveToFirst()) {
do {
result.add(c.getString(0));
} while (c.moveToNext());
}
}
} finally {
if (c != null) {
c.close();
}
}

大概代码的画风就是这个样子,先拼接出一个符合sql语法的字符串,上面也随机加了一写其他的操作指令字段排序和分页,使得查询指令看上去更加完整,然后使用游标来接收上面的查询结果。

可能大多数查询的时候会带上一些参数,比如where XX = XX 的过滤条件,假设有个需求需要在之前的查询用户需求上加上对出版社和图书价格的限制,则查询方式如下

String queryString =
"SELECT DISTINCT " + UserBookDao.Properties.UserName.columnName + " FROM " + UserBookDao.TABLENAME // 董铂然博客园
+ " WHERE "
+ UserBookDao.Properties.Publisher.columnName + " = ?"
+ " AND "
+ UserBookDao.Properties.Price.columnName + " > ?"
+ " ORDER BY "
+ UserBookDao.Properties.CreatedTime
+ " DESC "; ArrayList<String> result = new ArrayList<>();
Cursor c = mDaoSession.getDatabase().rawQuery(queryString, new String[]{"某出版社"),
String.valueOf(100.00)});
try {
if (c != null) {
if (c.moveToFirst()) {
do {
result.add(c.getString(0));
} while (c.moveToNext());
}
}
} finally {
if (c != null) {
c.close();
}
}

带上参数的查询字符串需要在上面使用问号占位,然后在下面用rawQuery带参数的api里填上相关的入参。

2. SELECT同时查询多个字段

还是用这个查书的例子,假设一下要查“书名”、“出版社”、“价格” 三个字段

String queryString = "SELECT "
+ UserBookDao.TABLENAME + "." + UserBookDao.Properties.BookName.columnName + ","
+ UserBookDao.TABLENAME + "." + UserBookDao.Properties.Publisher.columnName + ","
+ UserBookDao.TABLENAME + "." + UserBookDao.Properties.Price.columnName + " "
+ "FROM "
+ UserBookDao.TABLENAME + " "
+ "WHERE"
+ UserBookDao.Properties.Price + " > 100.00 ";
Cursor cursor = null;
try {
cursor = session.getDatabase().rawQuery(queryString,new String[]{});
if (cursor == null) {
return payMap;
}
// 取出三个字段分别对应的索引,下面再对着索引去取值
int nameIndex = cursor.getColumnIndex(UserBookDao.Properties.BookName.columnName);
int publisherIndex = cursor.getColumnIndex(UserBookDao.Properties.Publisher.columnName);
int priceIndex = cursor.getColumnIndex(UserBookDao.Properties.Price.columnName);
if (nameIndex != -1 && publisherIndex != -1 && priceIndex != -1) {
while (cursor.moveToNext()) {
String name = cursor.getString(nameIndex);
String publisher = cursor.getString(publisherIndex);
Double price = cursor.getDouble(priceIndex);
// 这里取到三个字段 自己是存模型还是字典 自己处理。
}
}
} finally {
if (null != cursor) {
cursor.close();
}
}

下面可以一次性的取出三个所需字段进行使用,需要先得到字段对应索引,然后再对着索引取值。

三、检测表字段是否存在

private boolean hasColumn(SQLiteDatabase db, String tableName, String column) {
if (TextUtils.isEmpty(tableName) || TextUtils.isEmpty(column)) {
return false;
}
Cursor cursor = null;
try {
cursor = db.query(tableName, null, null, null, null, null, null);
if (null != cursor && cursor.getColumnIndex(column) != -1) {
return true;
}
} finally {
if (null != cursor) {
cursor.close();
}
}
return false;
}

和上面取游标的方式类似,取出的列索引值如果不是-1,则代表能够取到这个字段返回true,否则和入参非法一起返回fasle。

四、数据库升级

这边会调用上面判断列名是否已经存在的方法。

然后重写父类的这个onUpgrade方法

private static class DemoOpenHelper extends DaoMaster.OpenHelper {
public DemoOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 数据库的版本控制 可以随着版本叠加不断增加差值
if (oldVersion < 2) {
if (!hasColumn(db, UserBookDao.TABLENAME, UserBookDao.Properties.Author.columnName)) {
String sql = "alter table " + UserBookDao.TABLENAME +
" add COLUMN " + UserBookDao.Properties.Author.columnName + " TEXT";
db.execSQL(sql);
}
if (!hasColumn(db, UserBookDao.TABLENAME, UserBookDao.Properties.Type.columnName)) {
String sql = "alter table " + UserBookDao.TABLENAME +
" add COLUMN " + UserBookDao.Properties.Type.columnName + " INTEGER";
db.execSQL(sql);
}
}
}
}

除了上面的修改表,如果改动太多或是换了表明,还可以直接删了重建(这么做的话之前的数据也就删了)

if (oldVersion < 3) {
UserDao.dropTable(new StandardDatabase(db),true);
UserStudentDao.createTable(new StandardDatabase(db),true);
}

五、数据库表字段赋初始值

有些字段的初始值如果你不希望是0,或是空字符串,可以赋初始值。现在的赋值初始值就分为两种情况了

1.建表时附初始值

在3.0以前的版本 还是要写一个module,里面写类似代码来建表的

private static void addUser(Schema schema) {
Entity user = schema.addEntity("User");
user.addIdProperty();
user.addStringProperty("name").notNull().defValue("\"jack\"");
user.addStringProperty("address");
user.addStringProperty("teacher");
user.addIntProperty("age").primJavaType().defValue("17");
}

在3.0之后推行用注解和直接写Entity的写法,所以可以直接在Entity的类里指定

@Entity
public class Student {
@Id(autoincrement = true)
private long id; //主键
private String name;
private String schoolTime = "09-01"; //开学时间默认都是9月1日
private int age = 19; // 刚上大学的默认都是19岁
// 下面生成的getter 和setter省略 。。。
}

2.数据库升级时给升级字段赋初始值

上面说的的数据库升级,是需要写一条alter table的sql语句,可以直接拼接到这一行后面

// 上面判断该列名是否存在
// ...
String sql = "alter table " + UserBookDao.TABLENAME +
" add COLUMN " + UserBookDao.Properties.Type.columnName + " INTEGER" + " NOT NULL DEFAULT(-1) "; // 直接拼接在语句最后 董铂然博客园
db.execSQL(sql);
// ...

注:以前听过一种说法是直接在UserDao这种生成的类里直接在生成的创建语句后面拼接DEFAULT,这里非常反对, 首先人家类名明确表明 // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.  并且有些人的代码可能设置的是手动生成,但我们的项目就在gradle里设置了每次build都会先自动生成一下,这种情况每次都会覆盖。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!

转自:http://www.jb51.net/article/101609.htm

安卓GreenDao框架一些进阶用法整理(转)的更多相关文章

  1. 安卓GreenDao框架一些进阶用法整理

    大致分为以下几个方面: 一些查询指令整理 使用SQL语句进行特殊查询 检测表字段是否存在 数据库升级 数据库表字段赋初始值 一.查询指令整理 1.链式执行的指令 return mDaoSession. ...

  2. ASP.NET Core 6框架揭秘实例演示[14]:日志的进阶用法

    为了对各种日志框架进行整合,微软创建了一个用来提供统一的日志编程模式的日志框架.<日志的基本编程模式>以实例演示的方式介绍了日志的基本编程模式,现在我们来补充几种"进阶" ...

  3. Django框架学习-Model进阶用法

    Model进阶用法 回顾 访问外键 访问多对多关系 更改数据库结构 当处理数据库结构改变时,需要注意到几点: 增加字段 首先在开发环境中: 再到产品环境中: 删除字段 删除多对多字段 删除model ...

  4. 前端自动化测试神器-Katalon进阶用法

    前言 上一篇介绍了Katalon的基础用法,本篇继续介绍一些进阶的用法. Keyword 和 Method Call Statement Keyword Keyword就是自定义方法,该方法在当前项目 ...

  5. Spring Data JPA系列3:JPA项目中核心场景与进阶用法介绍

    大家好,又见面了. 到这里呢,已经是本SpringData JPA系列文档的第三篇了,先来回顾下前面两篇: 在第1篇<Spring Data JPA系列1:JDBC.ORM.JPA.Spring ...

  6. Spring JdbcTemplate用法整理

    Spring JdbcTemplate用法整理: xml: <?xml version="1.0" encoding="UTF-8"?> <b ...

  7. canvas图形处理和进阶用法

    前面的话 上一篇博客介绍了canvas基础用法,本文将更进一步,介绍canvas的图形处理和进阶用法 图形变换 图形变换是指用数学方法调整所绘形状的物理属性,其实质是坐标变形.所有的变换都依赖于后台的 ...

  8. linq用法整理

    linq用法整理 普通查询 var highScores = from student in students where student.ExamScores[exam] > score se ...

  9. linux学习:特殊符号,数学运算,图像与数组与部分终端命令用法整理

    指令:let.expr.array.convert.tput.date.read.md5.ln.apt.系统信息 一:特殊符号用法整理 系统变量 $# 是传给脚本的参数个数 $0 是脚本本身的名字 $ ...

随机推荐

  1. PyCharm 安装使用

    服务器激活地址(转载)http://www.cnblogs.com/littlehb/p/7784517.html   PyCharm 服务器激活地址: 最近用edu邮箱申请了一个JetBrains针 ...

  2. django之Model类

    Model是model的基类,该类的metaclass是modelbase,在生成model类对象时是采用modelbase的.django.setup()时,apps会把app建立app_confi ...

  3. 使用MagicAJax的AjaxPanel时有时会弹出"Using the AjaxCallHelper write methods outside of an AjaxCall is not allowed."

    ------解决方案--------------------------------------------------------1.看下你的输出是不是包含在<ajax:AjaxPanel I ...

  4. TCP的窗口滑动机制

    TCP的滑动窗口主要有两个作用,一是提供TCP的可靠性,二是提供TCP的流控特性.同时滑动窗口机制还体现了TCP面向字节流的设计思路. 可靠:对发送的数据进行确认 流控制:窗口大小随链路变化. 一.t ...

  5. 查找nginx安装的路径

    你可以用这两个命令,找安装启用的路径 netstat -tnlp|grep nginx 然后看到一行记录,复制最后的一个数据(进程ID) ps -aux |grep 进程ID 就可以看到 NINGX的 ...

  6. python中Strip()函数的用法

    Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列. 注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符. str.strip([chars]) ...

  7. APP-8-文本语音

    1.百度语音合成JS文件 baidu_tts_cors.js /** * 浏览器调用语音合成接口 * @param {Object} param 百度语音合成接口参数 * 请参考 https://ai ...

  8. LeetCode 题解 Permutation Sequence 需要优化!

    题目大意:给出n和k,找到1..n这些数组成的有序全排列中的第k个. 首先,n的全排列可以分成n组,每一组由n-1个数组成. 例如  3的全排列,分成三组: 1 2 3  和 1 3 2 2 1 3 ...

  9. delphi dxBarManager 的dxBarEdit 输入问题

    Developer Express 6 想做像office2007那样界面. 问题:dxBarManager1 里面添加了cxBarEditItem1 这是个文本框,运行可以输入内容,但是当焦点失去时 ...

  10. ReactiveX 学习笔记(18)使用 RxJS + Angular 调用 REST API

    JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...