移動APP追求追求功能實現的同一時候,用戶體驗很重要。開始APP的同一時候。要時刻的切換開發人員的角色,如你開發的時候。是java
站在APP的開發角色,處於生產者的位置;當你測試的時候。你應該把本身放在用戶的角色上去考慮所作的APP了。舉一個很是easy的android
樣例,就像咱們每天使用手機上的新聞、好友動態等,當你沒有網絡的時候,也還有數據的存在提供用戶瀏覽,而不是一篇」白git
色「的。如同電腦死機通常。這就是移動APP在開發的時候,提供了最後一次網絡狀態下的數據緩存,提到數據緩存,可想而知有內github
存緩存、硬件緩存之分。在這我主要講述的是一個硬件緩存-----Android開發數據庫之第三方ORM框架(GreenDao)。sql
開發了那麼久的移動APP。近期工做量比較小,閒着沒事在對開發項目的性能進行優化。由於項目裏涉及了大量的緩存處理和數數據庫
據庫運用,需要對數據庫進行頻繁的讀寫、查詢等操做。所以首先想到了對整個項目的數據庫框架進行優化。api
原先使用android自己緩存
內置的sqllite,也就是用的最主要的SQLiteOpenHelper方法,這樣的方法對本身來講比較方便易懂。網絡
但是在使用過程當中感受很是繁瑣,框架
從建表到對錶的增刪改查等操做,假設表對象的屬性很是多,就需要使用大量的代碼來運行建表、插入等。在代碼運行中還需要對數
據庫和遊標的進行及時關閉(開啓使用,用完關閉),而且還需要部分sql語言。這在開發中產生bug進行調試時尤爲不方便。眼下
android經常用的orm框架主要有greenDAO、OrmLite、AndrORM。 綜合了網上的各類評價,greenDAO的執行效率最高。內存消耗最
少,性能最佳。
所以決定採用greenDAO框架。對項目的orm框架進行改進。
何以體現greenDAO的優點呢?如下 greenDAO與ORMLite性能對照:
通過幾天的改動,最終將項目裏的數據庫相關的都優化完了。
在這過程當中,發現greenDAO的性能確實不錯,而且使用至關方便。再也不需要涉及到不論什麼的sql語言。可以直接經過對象類進行建表、增刪改查等。尤爲是api接口又方便易懂。在摸索學習中發現國內相關學習資料實在實在是太少,遂決定在此記錄下本身對使用這個orm框架的一些心得和方法總結。
1、greenDAO框架相關資源
首先greenDAO做爲第三方的數據庫ORM框架。那必然有它的相關站點等資源。
一、greenDAO官網:http://greendao-orm.com/
二、項目下載地址:https://github.com/greenrobot/greenDAO(或者官網)
greenDAO是一個可以幫助Android開發人員高速將Java對象映射到SQLite數據庫的表單中的ORM解決方式,經過使用一個簡單的面向對象API,開發人員可以對Java對象進行存儲、更新、刪除和查詢。
greenDAO的主要設計目標:
*最大性能(最快的Android ORM)
*易於使用API
*高度優化
*最小內存消耗
2、開發使用步驟(重點)
一、下載greenDAO框架資源後,解壓分析官方Demo裏共同擁有六個project文件夾,分別爲:
(1).DaoCore:庫文件夾,即jar文件greendao-1.3.0-beta-1.jar的代碼。
(2).DaoExample:android範例project。
(3).DaoExampleGenerator:DaoExampleproject的DAO類構造器。javaproject;
(4).DaoGenerator:DAO類構造器。javaproject;
(5).DaoTest、PerformanceTestOrmLite:其它測試相關的project。
二、DAO類構造
首先需要新建一個javaproject來生成DAO類文件。該project需要導入greendao-generator.jar和freemarker.jar文件到項目中。
public class ExampleDaoGenerator
{
public static void main(String[] args) throws Exception
{
Schema schema = new Schema(3, "de.greenrobot.daoexample");
addNote(schema);
addCustomerOrder(schema);
new DaoGenerator().generateAll(schema, "../DaoExample/src-gen");
}
private static void addNote(Schema schema)
{
Entity note = schema.addEntity("Note");
note.addIdProperty();
note.addStringProperty("text").notNull();
note.addStringProperty("comment");
note.addDateProperty("date");
}
private static void addCustomerOrder(Schema schema)
{
Entity customer = schema.addEntity("Customer");
customer.addIdProperty();
customer.addStringProperty("name").notNull();
Entity order = schema.addEntity("Order");
order.setTableName("ORDERS"); // "ORDER" is a reserved key<a href="http://www.it165.net/edu/ebg/" target="_blank" class="keylink">word</a>
order.addIdProperty();
Property orderDate = order.addDateProperty("date").getProperty();
Property customerId = order.addLongProperty("customerId").notNull().getProperty();
order.addToOne(customer, customerId);
ToMany customerToOrders = customer.addToMany(order, customerId);
customerToOrders.setName("orders");
customerToOrders.orderAsc(orderDate);
}
}
在main方法中。分析例如如下:
Schema schema = new Schema(3, "de.greenrobot.daoexample");
該方法第一個參數用來更新數據庫版本,第二個參數爲要生成的DAO類所在包路徑。
而後進行建表和設置要生成DAO文件的目標project的項目路徑。
addNote(schema);
addCustomerOrder(schema);
new DaoGenerator().generateAll(schema, "../DaoExample/src-gen");
當中src-gen這個文件夾名需要在執行前手動建立。不然會報錯。
假設執行後出現下面錯誤,則導入DaoGenerator項目的dao.ftl文件就能夠(或者直接使用DaoGenerator來生成DAO文件)。
執行後出現下面的提示說明DAO文件本身主動生成成功了。刷新一下DaoExample項目就能夠看到。
執行後可以看到。DaoExample項目src-gen如下本身主動生成了8個文件,3個實體對象。3個dao,1個DaoMaster,1個DaoSession.
三、建立表
建立一個實體類
Entity note = schema.addEntity("Note");
默認表名就是類名。也可以本身定義表名
dao.setTableName("NoteList");
greenDAO會本身主動依據實體類屬性建立表字段,並賦予默認值。
好比在數據庫方面的表名和列名都來源於實體類名和屬性名。默認的數據庫名稱是大寫使用下劃線分隔單詞,而不是在Java中使用的駝峯式大寫和小寫風格。好比,一個名爲「CREATIONDATE」屬性將成爲一個數據庫列「CREATION_DATE」。
設置一個自增加ID列爲主鍵:
dao.addIdProperty().primaryKey().autoincrement();
設置其它各類類型的屬性:
dao.addIntProperty("cityId");
dao.addStringProperty("infoType").notNull();//非null字段
dao.addDoubleProperty("Id");
在生成的實體類中,int類型爲本身主動轉爲long類型。
假設在編譯過程當中出現下面錯誤,那麼有多是主鍵的類型錯誤所致:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
在使用greenDAO時,一個實體類僅僅能相應一個表。眼下無法作到一個表相應多個實體類。或者多個表共用一種對象類型。
興許的升級也不會針對這一點進行擴展。
四、表的增刪改查
增刪改查至關方便。全然的面向對象。不需要涉及到不論什麼的sql語言。
查詢
範例1:查詢某個表是否包括某個id:
public boolean isSaved(int ID)
{
QueryBuilder<SaveList> qb = saveListDao.queryBuilder();
qb.where(Properties.Id.eq(ID));
qb.buildCount().count();
return qb.buildCount().count() > 0 ?
true : false;
}
範例2:獲取整個表的數據集合,一句代碼就搞定!
public List<PhotoGalleryDB> getPhotoGallery()
{
return photoGalleryDao.loadAll();// 獲取圖片相冊
}
範例3:經過一個字段值查找相應的還有一個字段值(爲簡便直接使用如下方法,或許有更簡單的方法,還沒有嘗試)
/** 經過圖片id查找其文件夾id */
public int getTypeId(int picId)
{
QueryBuilder<PhotoGalleryDB> qb = photoGalleryDao.queryBuilder();
qb.where(Properties.Id.eq(picId));
if (qb.list().size() > 0)
{
return qb.list().get(0).getTypeId();
}
else
{
return -1;
}
}
範例4:查找所有第一姓名是「Joe」並且以lastname排序。
List joes = userDao.queryBuilder()
.where(Properties.FirstName.eq("Joe"))
.orderAsc(Properties.LastName)
.list();
範例5:多重條件查詢
(1)獲取id爲cityId並且infotype爲HBContant.CITYINFO_SL的數據集合:
public List<CityInfoDB> getSupportingList(int cityId)
{
QueryBuilder<CityInfoDB> qb = cityInfoDao.queryBuilder();
qb.where(qb.and(Properties.CityId.eq(cityId),Properties.InfoType.eq(HBContant.CITYINFO_SL)));
qb.orderAsc(Properties.Id);// 排序根據
return qb.list();
}
(2)獲取firstname爲「Joe」並且出生於1970年10月之後的所有user集合:
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();
範例6:獲取某列對象
picJsonDao.loadByRowId(picId);
5.增添/插入、改動
插入數據更加簡單。也是僅僅要一句代碼便能搞定!
public void addToPhotoTable(Photo p)
{
photoDao.insert(p);
}
插入時需要new一個新的對象,範比例如如下:
DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "notes-db", null);
db = helper.getWritableDatabase();
daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
noteDao = daoSession.getNoteDao();
Note note = new Note(null, noteText, comment, new Date());
noteDao.insert(note);
改動更新:
photoDao.insertOrReplace(photo);
photoDao.insertInTx(photo);
6.刪除:
(1)清空表格數據
/** 清空相冊圖片列表的數據 */
public void clearPhoto()
{
photoDao.deleteAll();
}
(2)刪除某個對象
{
QueryBuilder<DBCityInfo> qb = cityInfoDao.queryBuilder();
DeleteQuery<DBCityInfo> bd = qb.where(Properties.CityId.eq(cityId)).buildDelete();
bd.executeDeleteWithoutDetachingEntities();
}
由上可見,使用greenDAO進行數據庫的增刪改查時及其方便,而且性能極佳。
3、常常用法筆記
1.在Application實現獲得DaoMaster和DaoSession的方法:
private static DaoMaster daoMaster;
private static DaoSession daoSession;
/**
* 取得DaoMaster
*
* @param context
* @return
*/
public static DaoMaster getDaoMaster(Context context)
{
if (daoMaster == null)
{
OpenHelper helper = new DaoMaster.DevOpenHelper(context, HBContant.DATABASE_NAME, null);
daoMaster = new DaoMaster(helper.getWritableDatabase());
}
return daoMaster;
}
/**
* 取得DaoSession
*
* @param context
* @return
*/
public static DaoSession getDaoSession(Context context)
{
if (daoSession == null)
{
if (daoMaster == null)
{
daoMaster = getDaoMaster(context);
}
daoSession = daoMaster.newSession();
}
return daoSession;
}
2.增刪改查工具類:
public class DBHelper
{
private static Context mContext;
private static DBHelper instance;
private CityInfoDBDao cityInfoDao;
private DBHelper()
{
}
public static DBHelper getInstance(Context context)
{
if (instance == null)
{
instance = new DBHelper();
if (mContext == null)
{
mContext = context;
}
// 數據庫對象
DaoSession daoSession = HBApplication.getDaoSession(mContext);
instance.cityInfoDao = daoSession.getCityInfoDBDao();
}
return instance;
}
/** 加入數據 */
public void addToCityInfoTable(CityInfo item)
{
cityInfoDao.insert(item);
}
/** 查詢 */
public List<EstateLoveListJson> getCityInfoList()
{
QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
return qb.list();
}
/** 查詢 */
public List<CityInfo> getCityInfo()
{
return cityInfoDao.loadAll();// 查找圖片相冊
}
/** 查詢 */
public boolean isSaved(int Id)
{
QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
qb.where(Properties.Id.eq(Id));
qb.buildCount().count();
return qb.buildCount().count() > 0 ? true : false;// 查找收藏表
}
/** 刪除 */
public void deleteCityInfoList(int Id)
{
QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
DeleteQuery<CityInfo> bd = qb.where(Properties.Id.eq(Id)).buildDelete();
bd.executeDeleteWithoutDetachingEntities();
}
/** 刪除 */
public void clearCityInfo()
{
cityInfoDao.deleteAll();
}
/** 經過城市id查找其類型id */
public int getTypeId(int cityId)
{
QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
qb.where(Properties.Id.eq(cityId));
if (qb.list().size() > 0)
{
return qb.list().get(0).getTypeId();
}
else
{
return 0;
}
}
/** 多重查詢 */
public List<CityInfo> getIphRegionList(int cityId)
{
QueryBuilder<CityInfoDB> qb = cityInfoDao.queryBuilder();
qb.where(qb.and(Properties.CityId.eq(cityId), Properties.InfoType.eq(HBContant.CITYINFO_IR)));
qb.orderAsc(Properties.Id);// 排序根據
return qb.list();
}
}
另外。還有多表關聯、惰性載入等功能,待興許研究。
參考資料: 1.https://github.com/greenrobot/greenDAO 2.http://greendao-orm.com/documentation/how-to-get-started/ 3.http://blog.csdn.net/krislight/article/details/9391455