Android 快速開發系列 ORMLite 架構的使用,androidormlite

來源:互聯網
上載者:User

Android 快速開發系列 ORMLite 架構的使用,androidormlite

轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/39122981,本文出自【張鴻洋的部落格】

上一篇已經對ORMLite架構做了簡單的介紹:Android ORMLite 架構的入門用法~~本篇將介紹項目可能會使用到的一些用法,也為我們的使用ORMLite架構總結出一個較合理的用法。

通過上一篇的瞭解,我們使用ORMLite,需要自己寫一個DatabaseHelper去繼承OrmLiteSqliteOpenHelper,下面我們首先給出一個我認為比較靠譜的Helper的寫法:

1、DatabaseHelper

package com.zhy.zhy_ormlite.db;import java.sql.SQLException;import java.util.HashMap;import java.util.Map;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;import com.j256.ormlite.dao.Dao;import com.j256.ormlite.support.ConnectionSource;import com.j256.ormlite.table.TableUtils;import com.zhy.zhy_ormlite.bean.Article;import com.zhy.zhy_ormlite.bean.Student;import com.zhy.zhy_ormlite.bean.User;public  class DatabaseHelper extends OrmLiteSqliteOpenHelper{private static final String TABLE_NAME = "sqlite-test.db";private Map<String, Dao> daos = new HashMap<String, Dao>();private DatabaseHelper(Context context){super(context, TABLE_NAME, null, 4);}@Overridepublic void onCreate(SQLiteDatabase database,ConnectionSource connectionSource){try{TableUtils.createTable(connectionSource, User.class);TableUtils.createTable(connectionSource, Article.class);TableUtils.createTable(connectionSource, Student.class);} catch (SQLException e){e.printStackTrace();}}@Overridepublic void onUpgrade(SQLiteDatabase database,ConnectionSource connectionSource, int oldVersion, int newVersion){try{TableUtils.dropTable(connectionSource, User.class, true);TableUtils.dropTable(connectionSource, Article.class, true);TableUtils.dropTable(connectionSource, Student.class, true);onCreate(database, connectionSource);} catch (SQLException e){e.printStackTrace();}}private static DatabaseHelper instance;/** * 單例擷取該Helper *  * @param context * @return */public static synchronized DatabaseHelper getHelper(Context context){context = context.getApplicationContext();if (instance == null){synchronized (DatabaseHelper.class){if (instance == null)instance = new DatabaseHelper(context);}}return instance;}public synchronized Dao getDao(Class clazz) throws SQLException{Dao dao = null;String className = clazz.getSimpleName();if (daos.containsKey(className)){dao = daos.get(className);}if (dao == null){dao = super.getDao(clazz);daos.put(className, dao);}return dao;}/** * 釋放資源 */@Overridepublic void close(){super.close();for (String key : daos.keySet()){Dao dao = daos.get(key);dao = null;}}}

1、整個DatabaseHelper使用單例只對外公布出一個對象,保證app中只存在一個SQLite Connection , 參考文章:http://www.touchlab.co/2011/10/single-sqlite-connection/

2、我們對每個Bean建立一個XXXDao來處理當前Bean的資料庫操作,當然真正去和資料庫打交道的對象,通過上面代碼中的getDao(T t)進行擷取

getDao為一個泛型方法,會根據傳入Class對象進行建立Dao,並且使用一個Map來保持所有的Dao對象,只有第一次調用時才會去調用底層的getDao()。


2、Bean的Dao

package com.zhy.zhy_ormlite.db;import java.sql.SQLException;import android.content.Context;import com.j256.ormlite.dao.Dao;import com.zhy.zhy_ormlite.bean.User;public class UserDao{private Context context;private Dao<User, Integer> userDaoOpe;private DatabaseHelper helper;public UserDao(Context context){this.context = context;try{helper = DatabaseHelper.getHelper(context);userDaoOpe = helper.getDao(User.class);} catch (SQLException e){e.printStackTrace();}}/** * 增加一個使用者 * @param user */public void add(User user){try{userDaoOpe.create(user);} catch (SQLException e){e.printStackTrace();}}//...other operations}

我們的所有的XXXDao遵循以上的風格~

好了,基本瞭解了我們的代碼的結構~~ps:如果覺得不合理可以留言指出,如果覺得不能接收,直接忽略。。。


3、ORMLite外鍵引用

現在我們有兩張表一張User,一張Article; 

Article中當然需要儲存User的主鍵,作為關聯~~那麼在ORMLite中如何做到呢?

可能有人會直接在Article中聲明一個int類型userId屬性,當作普通屬性處理搞定,這種做法並沒有做,但是沒有體現出物件導向的思想。

物件導向是這樣的:Article屬於某個User

類這麼定義:

package com.zhy.zhy_ormlite.bean;import com.j256.ormlite.field.DatabaseField;import com.j256.ormlite.table.DatabaseTable;@DatabaseTable(tableName = "tb_article")public class Article{@DatabaseField(generatedId = true)private int id;@DatabaseFieldprivate String title;@DatabaseField(canBeNull = true, foreign = true, columnName = "user_id")private User user;public int getId(){return id;}public void setId(int id){this.id = id;}public String getTitle(){return title;}public void setTitle(String title){this.title = title;}public User getUser(){return user;}public void setUser(User user){this.user = user;}@Overridepublic String toString(){return "Article [id=" + id + ", title=" + title + ", user=" + user+ "]";}}

不會去定義一個int類型的userId,而是直接定義一個User成員變數,表示本Article屬於該User;

然後在User user屬性上添加:@DatabaseField(canBeNull = true, foreign = true, columnName = "user_id")

canBeNull -表示不能為null;foreign=true表示是一個外鍵;columnName 列名

User類暫且就兩個屬性:

package com.zhy.zhy_ormlite.bean;import com.j256.ormlite.field.DatabaseField;import com.j256.ormlite.table.DatabaseTable;@DatabaseTable(tableName = "tb_user")public class User {@DatabaseField(generatedId = true)private int id;@DatabaseField(columnName = "name")private String name;public User(){}public int getId(){return id;}public void setId(int id){this.id = id;}public String getName(){return name;}public void setName(String name){this.name = name;}@Overridepublic String toString(){return "User [id=" + id + ", name=" + name + "]";}}

現在看我們的ArticleDao

package com.zhy.zhy_ormlite.db;import java.sql.SQLException;import java.util.List;import android.content.Context;import com.j256.ormlite.dao.Dao;import com.zhy.zhy_ormlite.bean.Article;import com.zhy.zhy_ormlite.bean.User;public class ArticleDao{private Dao<Article, Integer> articleDaoOpe;private DatabaseHelper helper;@SuppressWarnings("unchecked")public ArticleDao(Context context){try{helper = DatabaseHelper.getHelper(context);articleDaoOpe = helper.getDao(Article.class);} catch (SQLException e){e.printStackTrace();}}/** * 添加一個Article * @param article */public void add(Article article){try{articleDaoOpe.create(article);} catch (SQLException e){e.printStackTrace();}}/** * 通過Id得到一個Article * @param id * @return */@SuppressWarnings("unchecked")public Article getArticleWithUser(int id){Article article = null;try{article = articleDaoOpe.queryForId(id);helper.getDao(User.class).refresh(article.getUser());} catch (SQLException e){e.printStackTrace();}return article;}/** * 通過Id得到一篇文章 * @param id * @return */public Article get(int id){Article article = null;try{article = articleDaoOpe.queryForId(id);} catch (SQLException e){e.printStackTrace();}return article;}/** * 通過UserId擷取所有的文章 * @param userId * @return */public List<Article> listByUserId(int userId){try{return articleDaoOpe.queryBuilder().where().eq("user_id", userId).query();} catch (SQLException e){e.printStackTrace();}return null;}}

接下來看我們的測試類別:

public class OrmLiteDbTest extends AndroidTestCase{public void testAddArticle(){User u = new User();u.setName("張鴻洋");new UserDao(getContext()).add(u);Article article = new Article();article.setTitle("ORMLite的使用");article.setUser(u);new ArticleDao(getContext()).add(article);}public void testGetArticleById(){Article article = new ArticleDao(getContext()).get(1);L.e(article.getUser() + " , " + article.getTitle());}public void testGetArticleWithUser(){Article article = new ArticleDao(getContext()).getArticleWithUser(1);L.e(article.getUser() + " , " + article.getTitle());}public void testListArticlesByUserId(){List<Article> articles = new ArticleDao(getContext()).listByUserId(1);L.e(articles.toString());}

分別測試,添加一個Article;通過Id擷取一個Article;通過Id擷取一個Article且攜帶User;通過userId擷取所有的Article;

主要看第三個:通過Id擷取一個Article且攜帶User,testGetArticleWithUser(id)

如何值傳一個Article的Id,然後能夠拿到Article對象,且內部的user屬性直接賦值呢?

兩種方式:

1、即上述寫法

article = articleDaoOpe.queryForId(id);helper.getDao(User.class).refresh(article.getUser());

2、在user屬性的註解上:@DatabaseField(canBeNull = true, foreign = true, columnName = "user_id", foreignAutoRefresh = true)

添加foreignAutoRefresh =true,這樣;當調用queryForId時,拿到Article對象則直接攜帶了user;


4、關聯一個集合

每個User關聯一個或多個Article,如果我在User中聲明一個Collection<Article> articles,我能否在查詢User的時候,一併能夠擷取到articles的值呢?

答案是可以的。在User中添加如下屬性,且註解如下:

@ForeignCollectionField
private Collection<Article> articles;

我們在UserDao中書寫查詢User的代碼:

public User get(int id){try{return userDaoOpe.queryForId(id);} catch (SQLException e){e.printStackTrace();}return null ;}

測試代碼:

public void testGetUserById(){User user = new UserDao(getContext()).get(1);L.e(user.getName());if (user.getArticles() != null)for (Article article : user.getArticles()){L.e(article.toString());}}
輸出:

09-07 22:49:06.484: E/zhy(7293): 張鴻洋09-07 22:49:06.484: E/zhy(7293): Article [id=1, title=ORMLite的使用]
可以看到,我們通過一個queryForId,成功的擷取了User,以及User關聯的所有的Articles;


5、條件查詢QueryBuilder的使用

上述代碼其實已經用到了簡單的條件查詢了:

1、簡單的where等於

articleDaoOpe.queryBuilder().where().eq("user_id", userId).query();直接返回Article的列表

2、where and 

QueryBuilder<Article, Integer> queryBuilder = articleDaoOpe.queryBuilder();Where<Article, Integer> where = queryBuilder.where();where.eq("user_id", 1);where.and();where.eq("name", "xxx");//或者articleDaoOpe.queryBuilder().//where().//eq("user_id", 1).and().//eq("name", "xxx");

上述兩種都相當與:select * from tb_article where user_id = 1 and name = 'xxx' ; 

3、更複雜的查詢

where.or(//where.and(//where.eq("user_id", 1), where.eq("name", "xxx")),where.and(//where.eq("user_id", 2), where.eq("name", "yyy")));

select * from tb_article where ( user_id = 1 and name = 'xxx' )  or ( user_id = 2 and name = 'yyy' )  ;

好了,再複雜的查詢估計也能夠湊出來了~~

6、updateBuilder、deleteBuilder

使用queryBuilder是因為我們希望執行完成查詢直接返回List<Bean>集合;

對於Update我們並不關注傳回值,直接使用

articleDaoOpe.updateRaw(statement, arguments);傳入sql和參數即可~~

何必在那articleDaoOpe.updateBuilder().updateColumnValue("name","zzz").where().eq("user_id", 1);這樣的痛苦呢~~~

同理還有deleteBuilder還是建議直接拼字sql,當然很簡單的除外,直接使用它的API~

7、事務操作

在我們的Dao中直接寫如下代碼:

//事務操作TransactionManager.callInTransaction(helper.getConnectionSource(),new Callable<Void>(){@Overridepublic Void call() throws Exception{return null;}});


8、其他動作

1、當Bean繼承BaseDaoEnabled時,可以使用bean.create(bean);bean.update(bean)一類操作

例如:

Student extends BaseDaoEnabled<Student, Integer>

Dao dao = DatabaseHelper.getHelper(getContext()).getDao(Student.class);
Student student = new Student();
student.setDao(dao);
student.setName("張鴻洋");
student.create();

前提dao需要手動設定,如果dao為null會報錯,尼瑪,我覺得一點用沒有。。。

2、Join

QueryBuilder<Article, Integer> articleBuilder = articleDaoOpe.queryBuilder();QueryBuilder userBuilder = helper.getDao(User.class).queryBuilder();articleBuilder.join(userBuilder);

Article與User做Join操作;


本篇主要想介紹在項目中如何寫DataBaseHelper已經如何寫BeanDao,以及列出了在項目中可能會用到的ORMLite的功能,如果需要詳細瞭解,還請看ORMLite官方文檔,源碼中也會提供~~



源碼點擊下載


 



android開發架構

json解析可以用google的gson包.
網路請求和緩衝機制(一般是指圖片緩衝吧)可以看看volley.
資料庫比較簡單,android內建的已經算是封裝過了.不過你可以看看Afinal裡面的FinalDb.
UI方面就沒有了.都是自己寫的.掌握好view和viewgroup.基本上所有控制項就掌握了.
 
android 五大應用開發架構是什

android應用開發架構是 Application Framework. 其系統架構由5部分組成,分別是:Linux Kernel、Android Runtime、Libraries、Application Framework、Applications。第二部分將詳細介紹這5個部分。下面自底向上分析各層。

Android架構

1、Linux Kernel

Android基於Linux 2.6提供核心系統服務,例如:安全、記憶體管理、進程管理、網路堆棧、驅動模型。Linux Kernel也作為硬體和軟體之間的抽象層,它隱藏具體硬體細節而為上層提供統一的服務。 如果你學過電腦網路知道OSI/RM,就會知道分層的好處就是使用下層提供的服務而為上層提供統一的服務,屏蔽本層及以下層的差異,當本層及以下層發生了變化不會影響到上層。也就是說各層各盡其職,各層提供固定的SAP(Service Access Point),專業點可以說是高內聚、低耦合。 如果你只是做應用開發,就不需要深入瞭解Linux Kernel層。

2、Android Runtime

Android包含一個核心庫的集合,提供大部分在Java程式設計語言核心類庫中可用的功能。每一個Android應用程式是Dalvik虛擬機器中的執行個體,運行在他們自己的進程中。Dalvik虛擬機器設計成,在一個裝置可以高效地運行多個虛擬機器。Dalvik虛擬機器可執行檔格式是.dex,dex格式是專為Dalvik設計的一種壓縮格式,適合記憶體和處理器速度有限的系統。 大多數虛擬機器包括JVM都是基於棧的,而Dalvik虛擬機器則是基於寄存器的。兩種架構各有優劣,一般而言,基於棧的機器需要更多指令,而基於寄存器的機器指令更大。dx 是一套工具,可以將 Java .class 轉換成 .dex 格式。一個dex檔案通常會有多個.class。由於dex有時必須進行最佳化,會使檔案大小增加1-4倍,以ODEX結尾。 Dalvik虛擬機器依賴於Linux 核心提供準系統,如線程和底層記憶體管理。

3、Libraries

Android包含一個C/C++庫的集合,供Android系統的各個組件使用。這些功能通過Android的應用程式架構(application framework)暴露給開發人員。下面列出一些核心庫: 系統C庫--標準C系統庫(libc)的BSD衍生,調整為基於嵌入式Linux裝置 媒體庫--基於PacketVideo的OpenCORE。這些庫支援播放和錄製許多流行的音頻和視頻格式,以及靜態影像檔,包括MPEG4、 H.264、 MP3、 AAC、 AMR、JPG、 PNG 介面管理--管理訪問顯示子系統和無縫組合多個應用程式的二維和三維圖形層 LibWebCore--新式的Web瀏覽器引擎,驅動Android 瀏覽器和內嵌的web視圖 SGL--基本的2D圖形引擎 3D庫--基於OpenGL ES 1.0 APIs的實現。庫使用硬體3D加速或包含高度最佳化的3D軟體光柵 FreeType --位元影像和向量字型渲染 SQLite --所有應用程式都可以使用的強大而輕量級的關聯式資料庫引擎

4、Application Framework

通過提供開放的開發平台,Android使開發人員能夠編製極其豐富和新穎的應用程式。開發人員可以自由地利用裝置硬體優勢、訪問位置資訊、運行後台服務、設定鬧鐘、向狀態列添加通知等等,很多很多。 開發人員可以完全使用核心應用程式所使用的架構APIs。應用程式的體繫結構旨......餘下全文>>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.