安卓GreenDao框架一些進(jìn)階用法整理
大致分為以下幾個(gè)方面:
- 一些查詢(xún)指令整理
- 使用SQL語(yǔ)句進(jìn)行特殊查詢(xún)
- 檢測(cè)表字段是否存在
- 數(shù)據(jù)庫(kù)升級(jí)
- 數(shù)據(jù)庫(kù)表字段賦初始值
一、查詢(xún)指令整理
1.鏈?zhǔn)綀?zhí)行的指令
return mDaoSession.getUserDao().queryBuilder(). XXX. XXX. XXX. list();
一般的查詢(xún)語(yǔ)句會(huì)在中間xxx的位置加上各種判斷和過(guò)濾的方法指令,除了最后的終結(jié)指令list()或unique()返回的是集合或業(yè)務(wù)對(duì)象,其他的都是返回QueryBuilder對(duì)象,大多數(shù)情況下XXX的位置都是填上where語(yǔ)句,還有一些其他和sql關(guān)聯(lián)的語(yǔ)句便于使用。
“whereOr” where語(yǔ)句里面寫(xiě)的條件都是用“且”連接,whereOr里的語(yǔ)句使用“或”連接
“distinct” 直接過(guò)濾掉重負(fù)字段
“l(fā)imit” 分頁(yè)n個(gè)一頁(yè),一般和offset結(jié)合使用
“offset” 忽略查詢(xún)出的前n條結(jié)果
“orderAsc” 以字段升序排序
“orderDesc”以字段降序
“preferLocalizedStringOrder” 本地化字符串排序
“orderCustom” 自定義排序 里面需要傳兩個(gè)參數(shù): 一個(gè)屬性 和對(duì)應(yīng)的排序方案 ASC 或是 DESC
“orderRaw” 也是自定義排序, 把字段和 排序方案 寫(xiě)在一個(gè)字符串傳入
“stringOrderCollation” 也是自定義排序 可以合并多個(gè)升降排序方案 以日期升序 且 價(jià)格降序
2.條件里的指令
return mDaoSession.getUserDao().queryBuilder(). where(UserDao.Properties.UserId.in(userIdList), UserDao.Properties.UserAge.eq(19)). list();
一個(gè)簡(jiǎn)單的where語(yǔ)句大概是這樣,在where的括號(hào)里面可以并列的寫(xiě)很多條件,其中全部以“且” 來(lái)連接。除了上面的“in”和“eq”還有很多其他判斷條件
“notEq” 和eq相反,別傻傻在再去外面敲“!”取反
“notIn” 同上
“or” 或者
“l(fā)ike” 就是sql語(yǔ)句的LIKE "%"+string+"%"
“between” 也就是BETWEEN ? AND ? 可以取兩個(gè)值的區(qū)間 (但是這條語(yǔ)句要慎用,不同的數(shù)據(jù)庫(kù)不一樣,有的是A<條件<B,有的是A<=條件<=B)
“gt” 相當(dāng)于 >
“ge”相當(dāng)于 >=
“l(fā)t” 相當(dāng)于 <
“l(fā)e”相當(dāng)于 <=
“isNull” 為空
“notIsNull” 不為空
二、使用SQL語(yǔ)句進(jìn)行特殊查詢(xún)
一般遇到普通的增刪改查操作無(wú)法輕易實(shí)現(xiàn)的功能,會(huì)使用這種rawQuery的方式。 我經(jīng)常遇到的也就是兩種場(chǎng)景:
1.使用SELECT DISTINCT
常用與一對(duì)多關(guān)系,假設(shè)圖書(shū)館現(xiàn)在有個(gè)“用戶(hù)存書(shū)表” 有的用戶(hù)有20本書(shū),表里就會(huì)有20條他的數(shù)據(jù),每條對(duì)應(yīng)一本不同的書(shū)。
這時(shí)假設(shè)有個(gè)需求,查出這個(gè)表中,所有的用戶(hù)名字,不許重復(fù)。 這時(shí)候用普通的查詢(xún)指令就會(huì)非常麻煩了,需要使用SELECT DISTINCT指令查出某列名所有不重復(fù)的條目。
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();
}
}
大概代碼的畫(huà)風(fēng)就是這個(gè)樣子,先拼接出一個(gè)符合sql語(yǔ)法的字符串,上面也隨機(jī)加了一寫(xiě)其他的操作指令字段排序和分頁(yè),使得查詢(xún)指令看上去更加完整,然后使用游標(biāo)來(lái)接收上面的查詢(xún)結(jié)果。
可能大多數(shù)查詢(xún)的時(shí)候會(huì)帶上一些參數(shù),比如where XX = XX 的過(guò)濾條件,假設(shè)有個(gè)需求需要在之前的查詢(xún)用戶(hù)需求上加上對(duì)出版社和圖書(shū)價(jià)格的限制,則查詢(xún)方式如下
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();
}
}
帶上參數(shù)的查詢(xún)字符串需要在上面使用問(wèn)號(hào)占位,然后在下面用rawQuery帶參數(shù)的api里填上相關(guān)的入?yún)ⅰ?/p>
2. SELECT同時(shí)查詢(xún)多個(gè)字段
還是用這個(gè)查書(shū)的例子,假設(shè)一下要查“書(shū)名”、“出版社”、“價(jià)格” 三個(gè)字段
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;
}
// 取出三個(gè)字段分別對(duì)應(yīng)的索引,下面再對(duì)著索引去取值
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);
// 這里取到三個(gè)字段 自己是存模型還是字典 自己處理。
}
}
} finally {
if (null != cursor) {
cursor.close();
}
}
下面可以一次性的取出三個(gè)所需字段進(jìn)行使用,需要先得到字段對(duì)應(yīng)索引,然后再對(duì)著索引取值。
三、檢測(cè)表字段是否存在
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;
}
和上面取游標(biāo)的方式類(lèi)似,取出的列索引值如果不是-1,則代表能夠取到這個(gè)字段返回true,否則和入?yún)⒎欠ㄒ黄鸱祷豧asle。
四、數(shù)據(jù)庫(kù)升級(jí)
這邊會(huì)調(diào)用上面判斷列名是否已經(jīng)存在的方法。
然后重寫(xiě)父類(lèi)的這個(gè)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) {
// 數(shù)據(jù)庫(kù)的版本控制 可以隨著版本疊加不斷增加差值
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);
}
}
}
}
除了上面的修改表,如果改動(dòng)太多或是換了表明,還可以直接刪了重建(這么做的話(huà)之前的數(shù)據(jù)也就刪了)
if (oldVersion < 3) {
UserDao.dropTable(new StandardDatabase(db),true);
UserStudentDao.createTable(new StandardDatabase(db),true);
}
五、數(shù)據(jù)庫(kù)表字段賦初始值
有些字段的初始值如果你不希望是0,或是空字符串,可以賦初始值?,F(xiàn)在的賦值初始值就分為兩種情況了
1.建表時(shí)附初始值
在3.0以前的版本 還是要寫(xiě)一個(gè)module,里面寫(xiě)類(lèi)似代碼來(lái)建表的
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之后推行用注解和直接寫(xiě)Entity的寫(xiě)法,所以可以直接在Entity的類(lèi)里指定
@Entity
public class Student {
@Id(autoincrement = true)
private long id; //主鍵
private String name;
private String schoolTime = "09-01"; //開(kāi)學(xué)時(shí)間默認(rèn)都是9月1日
private int age = 19; // 剛上大學(xué)的默認(rèn)都是19歲
// 下面生成的getter 和setter省略 。。。
}
2.數(shù)據(jù)庫(kù)升級(jí)時(shí)給升級(jí)字段賦初始值
上面說(shuō)的的數(shù)據(jù)庫(kù)升級(jí),是需要寫(xiě)一條alter table的sql語(yǔ)句,可以直接拼接到這一行后面
// 上面判斷該列名是否存在 // ... String sql = "alter table " + UserBookDao.TABLENAME + " add COLUMN " + UserBookDao.Properties.Type.columnName + " INTEGER" + " NOT NULL DEFAULT(-1) "; // 直接拼接在語(yǔ)句最后 董鉑然博客園 db.execSQL(sql); // ...
注:以前聽(tīng)過(guò)一種說(shuō)法是直接在UserDao這種生成的類(lèi)里直接在生成的創(chuàng)建語(yǔ)句后面拼接DEFAULT,這里非常反對(duì), 首先人家類(lèi)名明確表明 // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. 并且有些人的代碼可能設(shè)置的是手動(dòng)生成,但我們的項(xiàng)目就在gradle里設(shè)置了每次build都會(huì)先自動(dòng)生成一下,這種情況每次都會(huì)覆蓋。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)信號(hào)強(qiáng)度監(jiān)聽(tīng)的方法
這篇文章主要介紹了Android實(shí)現(xiàn)信號(hào)強(qiáng)度監(jiān)聽(tīng)的方法,是Android手機(jī)中很常見(jiàn)的一個(gè)實(shí)用功能,需要的朋友可以參考下2014-08-08
android使用Rxjava實(shí)現(xiàn)倒計(jì)時(shí)功能
這篇文章主要為大家詳細(xì)介紹了android使用Rxjava實(shí)現(xiàn)倒計(jì)時(shí)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
詳解Android封裝一個(gè)全局的BaseActivity
這篇文章主要介紹了詳解Android封裝一個(gè)全局的BaseActivity,對(duì)封裝感興趣的同學(xué),可以參考下2021-04-04
Flutter應(yīng)用程序?qū)崿F(xiàn)隱私屏幕示例解析
這篇文章主要為大家介紹了Flutter應(yīng)用程序?qū)崿F(xiàn)隱私屏幕示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
Flutter TV Android端開(kāi)發(fā)技巧詳細(xì)教程
這篇文章主要為大家介紹了Flutter TV Android端開(kāi)發(fā)技巧詳細(xì)教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Android OpenGL ES實(shí)現(xiàn)簡(jiǎn)單綠幕摳圖
這篇文章主要為大家介紹了Android OpenGL ES實(shí)現(xiàn)簡(jiǎn)單綠幕摳圖示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Libgdx解決部分Android機(jī)型鎖屏崩潰的方法
今天小編就為大家分享一篇關(guān)于Libgdx解決部分Android機(jī)型鎖屏崩潰的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10
Android 自定義View手寫(xiě)簽名并保存圖片功能
這篇文章主要介紹了Android 自定義View手寫(xiě)簽名并保存圖片功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2020-03-03
Android Studio連接手機(jī)設(shè)備教程
這篇文章主要為大家詳細(xì)介紹了Android Studio連接手機(jī)設(shè)備教程,非常完整的連接步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07

