GreenDao 3.X之基本使用
在 GreenDao 3.X之註解已經了解到GreenDao 3.0的改動及註解。對於數據庫的操作,無異於增刪改查等四個操作。下面我們將了解GreenDao 3.X如何使用?
AbstractDao
所有的自動生成的XXDao都是繼承於AbstractDao,此類中基本上封裝了所有的增刪改操作,包括數據庫的事務操作。常用的API如下:
void attachEntity(T entity): long count():獲取數據庫中數據的數量 // 數據刪除相關 void delete(T entity):從數據庫中刪除給定的實體void deleteAll() :刪除數據庫中全部數據 void deleteByKey(K key):從數據庫中刪除給定Key所對應的實體 void deleteByKeyInTx(java.lang.Iterable<K> keys):使用事務操作刪除數據庫中給定的所有key所對應的實體 void deleteByKeyInTx(K... keys):使用事務操作刪除數據庫中給定的所有key所對應的實體 void deleteInTx(java.lang.Iterable<T> entities):使用事務操作刪除數據庫中給定實體集合中的實體void deleteInTx(T... entities):使用事務操作刪除數據庫中給定的實體 // 數據插入相關 long insert(T entity):將給定的實體插入數據庫 void insertInTx(java.lang.Iterable<T> entities):使用事務操作,將給定的實體集合插入數據庫 void insertInTx(java.lang.Iterable<T> entities, boolean setPrimaryKey):使用事務操作,將給定的實體集合插入數據庫, 並設置是否設定主鍵void insertInTx(T... entities):將給定的實體插入數據庫 long insertOrReplace(T entity):將給定的實體插入數據庫,若此實體類存在,則覆蓋 void insertOrReplaceInTx(java.lang.Iterable<T> entities):使用事務操作,將給定的實體插入數據庫,若此實體類存在,則覆蓋 void insertOrReplaceInTx(java.lang.Iterable<T> entities, boolean setPrimaryKey):使用事務操作,將給定的實體插入數據庫,若此實體類存在,則覆蓋 並設置是否設定主鍵 void insertOrReplaceInTx(T... entities):使用事務操作,將給定的實體插入數據庫,若此實體類存在,則覆蓋 long insertWithoutSettingPk(T entity):將給定的實體插入數據庫,但不設定主鍵 // 新增數據插入相關API void save(T entity):將給定的實體插入數據庫,若此實體類存在,則更新 void saveInTx(java.lang.Iterable<T> entities):將給定的實體插入數據庫,若此實體類存在,則更新 void saveInTx(T... entities):使用事務操作,將給定的實體插入數據庫,若此實體類存在,則更新 // 加載相關 T load(K key):加載給定主鍵的實體 java.util.List<T> loadAll():加載數據庫中所有的實體 protected java.util.List<T> loadAllAndCloseCursor(android.database.Cursor cursor) :從cursor中讀取、返回實體的列表,並關閉該cursor protected java.util.List<T> loadAllFromCursor(android.database.Cursor cursor):從cursor中讀取、返回實體的列表 T loadByRowId(long rowId) :加載某一行並返回該行的實體 protected T loadUnique(android.database.Cursor cursor) :從cursor中讀取、返回唯一實體 protected T loadUniqueAndCloseCursor(android.database.Cursor cursor) :從cursor中讀取、返回唯一實體,並關閉該cursor //更新數據 void update(T entity) :更新給定的實體 protected void updateInsideSynchronized(T entity, DatabaseStatement stmt, boolean lock) protected void updateInsideSynchronized(T entity, android.database.sqlite.SQLiteStatement stmt, boolean lock) void updateInTx(java.lang.Iterable<T> entities) :使用事務操作,更新給定的實體 void updateInTx(T... entities):使用事務操作,更新給定的實體
QueryBuilder、Query
基本查詢
GreenDao中,使用QueryBuilder自定義查詢實體,而不是再寫繁瑣的SQL語句,避免了SQL語句的出錯率。大家都知道寫SQL語句時,非常容易出錯,出錯後又十分的難查。QueryBuilder真是幫忙解決了一個大麻煩。具體該如何使用呢?
List joes = userDao.queryBuilder() // 查詢的條件 .where(Properties.FirstName.eq("Joe")) // 返回實體集合升序排列 .orderAsc(Properties.LastName) .list(); QueryBuilder qb = userDao.queryBuilder(); // 查詢的條件 qb.where(Properties.FirstName.eq("Joe"), qb.or(Properties.YearOfBirth.gt(1970), qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10)))); List youngJoes = qb.list(); </span>
上面是官方給出的兩個列子,不僅滿足了查詢語句的易寫,同時使用了流式寫法,提高了代碼的可閱讀性。
Limit、Offset、Pagination
在實際開發過程中,大家肯定碰到這樣的問題,當數據過多在一頁顯示不出來的時候,要麽選擇前面十條顯示,要麽分頁顯示,但是數據總是獲取全部的。其實,剛接觸GreenDao的時候,也是這麽幹,獲取全部的實體集合,然後再根據實際情況截取。看了API以後,豁然開朗,大神們已經幫我們解決了這件事。此時不得不說,QueryBuilder
中的Limit(限制)、Offset(偏移),limit(int)和offset(int)協同設置,可以完美解決分頁顯示。
limit(int):限制查詢返回結果的數目 offset(int):設置查詢結果的偏移量,此查詢需與limit(int)結合使用,而不能夠脫離limit(int)單獨使用
Query
當執行多次查詢時,實際是QueryBuilder多次調用Query類。如果執行多次相同的查詢,應使用QueryBuilder的build()方法來創建Query,而不是直接使用Query類。如果查詢返回的結果是唯一性的,可以使用操作符方法,如果不希望此唯一性不返回 null,此時可調用uniqOrThrow()方法。如果查詢返回的結果是多個,可以使返回的結果是一個集合,有如下方法:
list():所有實體加載至內存,結果通常是一個ArrayList
listLazy():實體在需要時,加載至內存,表中的第一個元素被第一次訪問時會被緩存,下次訪問時,使用緩存
listLazyUncached():任何對列表實體的訪問懂事從數據庫中加載
listIterator():以按需加載的方式來遍歷結果,數據沒有被緩存
一旦使用QueryBuilder創建了一個query,那麽這個Query對象就可以就可以被復用來執行查詢顯然這種方式逼重新創建一次Query效率要高。
具體來說:
如果Query的參數沒有變更,你只需要再次調用List/unuque方法即可
如果參數發生了變化,那麽就需要通過setParameter方法來處理每一個發生改變的參數
舉例:
Query query = userDao.queryBuilder().where(Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970)).build(); List joesOf1970 = query.list();
現在復用該Query對象:
query.setParameter(0, "Maria"); query.setParameter(1, 1977); List mariasOf1977 = query.list();
由此可見,Query在執行一次build之後會將查詢結果進行緩存,方便下次繼續使用。
執行原生SQL語句
兩種方法:
Query query = userDao.queryBuilder().where( new StringCondition("_ID IN " + "(SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)").build();
如果這裏的QueryBuilder沒有提供你想要的特性,可以使用原始的queryRaw或queryRawCreate方法。
Query query = userDao.queryRawCreate( ", GROUP G WHERE G.NAME=? AND T.GROUP_ID=G._ID", "admin"
註:寫SQL語句時推薦定義常量來表示表名或者表項,這樣可以防止出錯,因為編譯器會檢查
基本使用
創建實體類
@Entity(generateConstructors = false) public class Student { @Id private Long id; private String name; private int age; public Student() { } @Keep public Student(String name, int age) { this.name = name; this.age = age; } public Student(Long id, String name, int age) { this.id = id; this.name = name; this.age = age; } @Keep public Long getId() { return id; } @Keep public void setId(Long id) { this.id = id; } @Keep public String getName() { return name; } @Keep public void setName(String name) { this.name = name; } @Keep public int getAge() { return age; } @Keep public void setAge(int age) { this.age = age; } @Keep @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Student)) return false; Student student = (Student) o; return name.equals(student.name); } @Keep @Override public int hashCode() { return (int) (id ^ (id >>> 32)); } @Keep @Override public String toString() { return "Student{" + "id=" + id + ", name=‘" + name + ‘\‘‘ + ", age=" + age + ‘}‘; } }
創建完實體類後,Rebuild Project生成DaoMaster、DaoSession。DaoMaster、DaoSession位於在Gradle設置的目錄及文件夾裏。
創建Database管理類
public class DbManager { // 是否加密 public static final boolean ENCRYPTED = true; private static final String DB_NAME = "tea.db"; private static DbManager mDbManager; private static DaoMaster.DevOpenHelper mDevOpenHelper; private static DaoMaster mDaoMaster; private static DaoSession mDaoSession; private Context mContext; private DbManager(Context context) { this.mContext = context; // 初始化數據庫信息 mDevOpenHelper = new DaoMaster.DevOpenHelper(context, DB_NAME); getDaoMaster(context); getDaoSession(context); } public static DbManager getInstance(Context context) { if (null == mDbManager) { synchronized (DbManager.class) { if (null == mDbManager) { mDbManager = new DbManager(context); } } } return mDbManager; } /** * @desc 獲取可讀數據庫 * @autor Tiany * @time 2016/8/13 **/ public static SQLiteDatabase getReadableDatabase(Context context) { if (null == mDevOpenHelper) { getInstance(context); } return mDevOpenHelper.getReadableDatabase(); } /** * @desc 獲取可寫數據庫 * @autor Tiany * @time 2016/8/13 **/ public static SQLiteDatabase getWritableDatabase(Context context) { if (null == mDevOpenHelper) { getInstance(context); } return mDevOpenHelper.getWritableDatabase(); } /** * @desc 獲取DaoMaster * @autor Tiany * @time 2016/8/13 **/ public static DaoMaster getDaoMaster(Context context) { if (null == mDaoMaster) { synchronized (DbManager.class) { if (null == mDaoMaster) { mDaoMaster = new DaoMaster(getWritableDatabase(context)); } } } return mDaoMaster; } /** * @desc 獲取DaoSession * @autor Tiany * @time 2016/8/13 **/ public static DaoSession getDaoSession(Context context) { if (null == mDaoSession) { synchronized (DbManager.class) { mDaoSession = getDaoMaster(context).newSession(); } } return mDaoSession; } } 數據庫操作類 [java] view plain copy public class StudentDaoOpe { /** * @desc 添加數據至數據庫 * @autor Tiany * @time 2016/8/13 **/ public static void insertData(Context context, Student stu) { DbManager.getDaoSession(context).getStudentDao().insert(stu); } /** * @desc 將數據實體通過事務添加至數據庫 * @autor Tiany * @time 2016/8/13 **/ public static void insertData(Context context, List<Student> list) { if (null == list || list.size() <= 0) { return; } DbManager.getDaoSession(context).getStudentDao().insertInTx(list); } /** * @desc 添加數據至數據庫,如果存在,將原來的數據覆蓋 * @autor Tiany * @time 2016/8/15 **/ public static void saveData(Context context, Student student) { DbManager.getDaoSession(context).getStudentDao().save(student); } /** * @desc 查詢所有數據 * @autor Tiany * @time 2016/8/15 **/ public static List<Student> queryAll(Context context) { QueryBuilder<Student> builder = DbManager.getDaoSession(context).getStudentDao().queryBuilder(); return builder.build().list(); } }
到此為止,數據庫的基本操作已完成,根據實際需求笤俑數據庫操作類相應的操作即可。
現流行RxJava異步及流式開發,GreenDao已將RxJava集成,具體的使用見
參考文檔
1、官方文檔
2.、GreenDAO 3.0 初次使用
GreenDao 3.X之基本使用