安卓GreenDao架構一些進階用法整理

來源:互聯網
上載者:User

標籤:offset   while   creat   返回   from   this   super   項目   gre   

大致分為以下幾個方面:

  • 一些查詢指令整理
  • 使用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,或是Null 字元串,可以賦初始值。現在的賦值初始值就分為兩種情況了

 

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的類裡指定

@Entitypublic 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都會先自動產生一下,這種情況每次都會覆蓋。

 

開發中一些整理,歡迎討論。

安卓GreenDao架構一些進階用法整理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.