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

大致分为以下几个方面:

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

一、查询指令整理

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都会先自动生成一下,这种情况每次都会覆盖。

开发中一些整理,欢迎讨论。

时间: 2024-10-12 17:40:14

安卓GreenDao框架一些进阶用法整理的相关文章

Django框架学习-Model进阶用法

Model进阶用法 回顾 访问外键 访问多对多关系 更改数据库结构 当处理数据库结构改变时,需要注意到几点: 增加字段 首先在开发环境中: 再到产品环境中: 删除字段 删除多对多字段 删除model Manager管理器 给管理器添加新的方法 修改返回的QuerySet Model的方法 执行自定义SQL语句 Model进阶用法 回顾 Django中的model层主要和数据库进行交互,使用数据库API对数据库进行增删改查的操作. 下面将介绍关于model层更深入的用法. 下面是之前创建model

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

前言 上一篇介绍了Katalon的基础用法,本篇继续介绍一些进阶的用法. Keyword 和 Method Call Statement Keyword Keyword就是自定义方法,该方法在当前项目下公共可用(当然,也可以将文件考到别的项目中进行复用),而Method Call Statement则更多的是用在局部定义的方法的调用上. 在项目的Keywords目录下,创建my.test.kits包,并创建TestUtilities.groovy类,其代码为: public class Test

Google Guava 库用法整理&lt;转&gt;

参考: http://codemunchies.com/2009/10/beautiful-code-with-google-collections-guava-and-static-imports-part-1/(2,3,4) http://blog.publicobject.com 更多用法参考http://ajoo.iteye.com/category/119082 附 guava中文api地址http://ifeve.com/google-guava/ 以前这么用: Java代码   M

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

一:特殊符号用法整理 算术比较-eq 等于-ne 不等于-gt 大于-lt 小于-ge 大于或等于-le 小于或等于-a 逻辑与 and &&-o 逻辑或 or ||[ $var -eq 0 ]    #当$var等于0时,返回真[ $var -ne 0 ]    #当$var为非0时,返回真[ $var1 -ne 0 -a $var2 -gt 2 ][ $var1 -ne 0 -o $var2 -gt 2 ] 字符串比较[[ $str1 = $str2 ]]     #当str1等于st

C++ List的用法(整理)

来源:http://blog.csdn.net/lskyne/article/details/10418823 C++ List的用法(整理) 2013-08-27 23:04 42624人阅读 评论(2) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转载. Lists将元素按顺序储存在链表中. 与 向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢. assign() 给list赋值 back() 返回最后一个元素 begin() 返回指向第一个元素的迭代

Spring JdbcTemplate用法整理

Spring JdbcTemplate用法整理: xml: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www

MySQL中使用SHOW PROFILE命令分析性能的用法整理(配合explain效果更好,可以作为优化周期性检查)

这篇文章主要介绍了MySQL中使用show profile命令分析性能的用法整理,show profiles是数据库性能优化的常用命令,需要的朋友可以参考下 show profile是由Jeremy Cole捐献给MySQL社区版本的.默认的是关闭的,但是会话级别可以开启这个功能.开启它可以让MySQL收集在执行语句的时候所使用的资源.为了统计报表,把profiling设为1 mysql> SET profiling = 1; 之后在运行一个查询 mysql> SELECT COUNT(DIS

线程框架Executor的用法举例

java5线程框架Executor的用法举例 Executor 是 java5 下的一个多任务并发执行框架(Doug Lea),可以建立一个类似数据库连接池的线程池来执行任务.这个框架主要由三个接口和其相应的具体类组成.Executor. ExecutorService 和 ScheduledExecutorService . 1. Executor 接口:是用来执行 Runnable 任务的:它只定义一个方法- execute(Runnable command):执行 Ruannable 类型

SQL 系统存储过程用法整理

---------------------------------------------------------------------------------- -- Author : htl258(Tony) -- Date   : 2010-07-06 23:13:19 -- Version: Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (Intel X86) --          Jul  9 2008 14:43:34 --