Android 快速開發系列 ORMLite 框架最佳實踐

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

經過上一篇的瞭解,咱們使用ORMLite,須要本身寫一個DatabaseHelper去繼承OrmLiteSqliteOpenHelper,下面咱們首先給出一個我認爲比較靠譜的Helper的寫法:android

一、DatabaseHelper

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片sql

  1. package com.zhy.zhy_ormlite.db;  數據庫

  2.   

  3. import java.sql.SQLException;  app

  4. import java.util.HashMap;  框架

  5. import java.util.Map;  ide

  6.   

  7. import android.content.Context;  測試

  8. import android.database.sqlite.SQLiteDatabase;  ui

  9.   

  10. import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;  this

  11. import com.j256.ormlite.dao.Dao;  

  12. import com.j256.ormlite.support.ConnectionSource;  

  13. import com.j256.ormlite.table.TableUtils;  

  14. import com.zhy.zhy_ormlite.bean.Article;  

  15. import com.zhy.zhy_ormlite.bean.Student;  

  16. import com.zhy.zhy_ormlite.bean.User;  

  17.   

  18. public  class DatabaseHelper extends OrmLiteSqliteOpenHelper  

  19. {  

  20.     private static final String TABLE_NAME = "sqlite-test.db";  

  21.   

  22.     private Map<String, Dao> daos = new HashMap<String, Dao>();  

  23.   

  24.     private DatabaseHelper(Context context)  

  25.     {  

  26.         super(context, TABLE_NAME, null4);  

  27.     }  

  28.   

  29.     @Override  

  30.     public void onCreate(SQLiteDatabase database,  

  31.             ConnectionSource connectionSource)  

  32.     {  

  33.         try  

  34.         {  

  35.             TableUtils.createTable(connectionSource, User.class);  

  36.             TableUtils.createTable(connectionSource, Article.class);  

  37.             TableUtils.createTable(connectionSource, Student.class);  

  38.         } catch (SQLException e)  

  39.         {  

  40.             e.printStackTrace();  

  41.         }  

  42.     }  

  43.   

  44.     @Override  

  45.     public void onUpgrade(SQLiteDatabase database,  

  46.             ConnectionSource connectionSource, int oldVersion, int newVersion)  

  47.     {  

  48.         try  

  49.         {  

  50.             TableUtils.dropTable(connectionSource, User.classtrue);  

  51.             TableUtils.dropTable(connectionSource, Article.classtrue);  

  52.             TableUtils.dropTable(connectionSource, Student.classtrue);  

  53.             onCreate(database, connectionSource);  

  54.         } catch (SQLException e)  

  55.         {  

  56.             e.printStackTrace();  

  57.         }  

  58.     }  

  59.   

  60.     private static DatabaseHelper instance;  

  61.   

  62.     /** 

  63.      * 單例獲取該Helper 

  64.      *  

  65.      * @param context 

  66.      * @return  

  67.      */  

  68.     public static synchronized DatabaseHelper getHelper(Context context)  

  69.     {  

  70.         context = context.getApplicationContext();  

  71.         if (instance == null)  

  72.         {  

  73.             synchronized (DatabaseHelper.class)  

  74.             {  

  75.                 if (instance == null)  

  76.                     instance = new DatabaseHelper(context);  

  77.             }  

  78.         }  

  79.   

  80.         return instance;  

  81.     }  

  82.   

  83.     public synchronized Dao getDao(Class clazz) throws SQLException  

  84.     {  

  85.         Dao dao = null;  

  86.         String className = clazz.getSimpleName();  

  87.   

  88.         if (daos.containsKey(className))  

  89.         {  

  90.             dao = daos.get(className);  

  91.         }  

  92.         if (dao == null)  

  93.         {  

  94.             dao = super.getDao(clazz);  

  95.             daos.put(className, dao);  

  96.         }  

  97.         return dao;  

  98.     }  

  99.   

  100.     /** 

  101.      * 釋放資源 

  102.      */  

  103.     @Override  

  104.     public void close()  

  105.     {  

  106.         super.close();  

  107.   

  108.         for (String key : daos.keySet())  

  109.         {  

  110.             Dao dao = daos.get(key);  

  111.             dao = null;  

  112.         }  

  113.     }  

  114.   

  115. }  


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

二、咱們對每一個Bean建立一個XXXDao來處理當前Bean的數據庫操做,固然真正去和數據庫打交道的對象,經過上面代碼中的getDao(T t)進行獲取

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


二、Bean的Dao

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. package com.zhy.zhy_ormlite.db;  

  2.   

  3. import java.sql.SQLException;  

  4.   

  5. import android.content.Context;  

  6.   

  7. import com.j256.ormlite.dao.Dao;  

  8. import com.zhy.zhy_ormlite.bean.User;  

  9.   

  10. public class UserDao  

  11. {  

  12.     private Context context;  

  13.     private Dao<User, Integer> userDaoOpe;  

  14.     private DatabaseHelper helper;  

  15.   

  16.     public UserDao(Context context)  

  17.     {  

  18.         this.context = context;  

  19.         try  

  20.         {  

  21.             helper = DatabaseHelper.getHelper(context);  

  22.             userDaoOpe = helper.getDao(User.class);  

  23.         } catch (SQLException e)  

  24.         {  

  25.             e.printStackTrace();  

  26.         }  

  27.     }  

  28.   

  29.     /** 

  30.      * 增長一個用戶 

  31.      * @param user 

  32.      */  

  33.     public void add(User user)  

  34.     {  

  35.         try  

  36.         {  

  37.             userDaoOpe.create(user);  

  38.         } catch (SQLException e)  

  39.         {  

  40.             e.printStackTrace();  

  41.         }  

  42.   

  43.     }//...other operations  

  44.   

  45.   

  46. }  


咱們的全部的XXXDao遵循以上的風格~

好了,基本瞭解了咱們的代碼的結構~~ps:若是以爲不合理能夠留言指出,若是以爲不能接收,直接忽略。。。


三、ORMLite外鍵引用

如今咱們有兩張表一張User,一張Article; 

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

可能有人會直接在Article中聲明一個int類型userId屬性,看成普通屬性處理搞定,這種作法並無作,可是沒有體現出面向對象的思想。

面向對象是這樣的:Article屬於某個User

類這麼定義:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. package com.zhy.zhy_ormlite.bean;  

  2.   

  3. import com.j256.ormlite.field.DatabaseField;  

  4. import com.j256.ormlite.table.DatabaseTable;  

  5.   

  6. @DatabaseTable(tableName = "tb_article")  

  7. public class Article  

  8. {  

  9.     @DatabaseField(generatedId = true)  

  10.     private int id;  

  11.     @DatabaseField  

  12.     private String title;  

  13.     @DatabaseField(canBeNull = true, foreign = true, columnName = "user_id")  

  14.     private User user;  

  15.   

  16.     public int getId()  

  17.     {  

  18.         return id;  

  19.     }  

  20.   

  21.     public void setId(int id)  

  22.     {  

  23.         this.id = id;  

  24.     }  

  25.   

  26.     public String getTitle()  

  27.     {  

  28.         return title;  

  29.     }  

  30.   

  31.     public void setTitle(String title)  

  32.     {  

  33.         this.title = title;  

  34.     }  

  35.   

  36.     public User getUser()  

  37.     {  

  38.         return user;  

  39.     }  

  40.   

  41.     public void setUser(User user)  

  42.     {  

  43.         this.user = user;  

  44.     }  

  45.   

  46.     @Override  

  47.     public String toString()  

  48.     {  

  49.         return "Article [id=" + id + ", title=" + title + ", user=" + user  

  50.                 + "]";  

  51.     }  

  52.   

  53. }  


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

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

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

User類暫且就兩個屬性:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. package com.zhy.zhy_ormlite.bean;  

  2.   

  3. import com.j256.ormlite.field.DatabaseField;  

  4. import com.j256.ormlite.table.DatabaseTable;  

  5.   

  6. @DatabaseTable(tableName = "tb_user")  

  7. public class User   

  8. {  

  9.     @DatabaseField(generatedId = true)  

  10.     private int id;  

  11.     @DatabaseField(columnName = "name")  

  12.     private String name;  

  13.   

  14.   

  15.     public User()  

  16.     {  

  17.     }  

  18.   

  19.     public int getId()  

  20.     {  

  21.         return id;  

  22.     }  

  23.   

  24.     public void setId(int id)  

  25.     {  

  26.         this.id = id;  

  27.     }  

  28.   

  29.     public String getName()  

  30.     {  

  31.         return name;  

  32.     }  

  33.   

  34.     public void setName(String name)  

  35.     {  

  36.         this.name = name;  

  37.     }  

  38.   

  39.     @Override  

  40.     public String toString()  

  41.     {  

  42.         return "User [id=" + id + ", name=" + name   

  43.                 + "]";  

  44.     }  

  45.   

  46.       

  47.   

  48.   

  49.       

  50. }  


如今看咱們的ArticleDao

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. package com.zhy.zhy_ormlite.db;  

  2.   

  3. import java.sql.SQLException;  

  4. import java.util.List;  

  5.   

  6. import android.content.Context;  

  7.   

  8. import com.j256.ormlite.dao.Dao;  

  9. import com.zhy.zhy_ormlite.bean.Article;  

  10. import com.zhy.zhy_ormlite.bean.User;  

  11.   

  12. public class ArticleDao  

  13. {  

  14.     private Dao<Article, Integer> articleDaoOpe;  

  15.     private DatabaseHelper helper;  

  16.   

  17.     @SuppressWarnings("unchecked")  

  18.     public ArticleDao(Context context)  

  19.     {  

  20.         try  

  21.         {  

  22.             helper = DatabaseHelper.getHelper(context);  

  23.             articleDaoOpe = helper.getDao(Article.class);  

  24.         } catch (SQLException e)  

  25.         {  

  26.             e.printStackTrace();  

  27.         }  

  28.     }  

  29.   

  30.     /** 

  31.      * 添加一個Article 

  32.      * @param article 

  33.      */  

  34.     public void add(Article article)  

  35.     {  

  36.         try  

  37.         {  

  38.             articleDaoOpe.create(article);  

  39.         } catch (SQLException e)  

  40.         {  

  41.             e.printStackTrace();  

  42.         }  

  43.     }  

  44.   

  45.     /** 

  46.      * 經過Id獲得一個Article 

  47.      * @param id 

  48.      * @return 

  49.      */  

  50.     @SuppressWarnings("unchecked")  

  51.     public Article getArticleWithUser(int id)  

  52.     {  

  53.         Article article = null;  

  54.         try  

  55.         {  

  56.             article = articleDaoOpe.queryForId(id);  

  57.             helper.getDao(User.class).refresh(article.getUser());  

  58.   

  59.         } catch (SQLException e)  

  60.         {  

  61.             e.printStackTrace();  

  62.         }  

  63.         return article;  

  64.     }  

  65.       

  66.     /** 

  67.      * 經過Id獲得一篇文章 

  68.      * @param id 

  69.      * @return 

  70.      */  

  71.     public Article get(int id)  

  72.     {  

  73.         Article article = null;  

  74.         try  

  75.         {  

  76.             article = articleDaoOpe.queryForId(id);  

  77.   

  78.         } catch (SQLException e)  

  79.         {  

  80.             e.printStackTrace();  

  81.         }  

  82.         return article;  

  83.     }  

  84.   

  85.     /** 

  86.      * 經過UserId獲取全部的文章 

  87.      * @param userId 

  88.      * @return 

  89.      */  

  90.     public List<Article> listByUserId(int userId)  

  91.     {  

  92.         try  

  93.         {  

  94.             return articleDaoOpe.queryBuilder().where().eq("user_id", userId)  

  95.                     .query();  

  96.         } catch (SQLException e)  

  97.         {  

  98.             e.printStackTrace();  

  99.         }  

  100.         return null;  

  101.     }  

  102.   

  103. }  


接下來看咱們的測試類:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public class OrmLiteDbTest extends AndroidTestCase  

  2. {  

  3.     public void testAddArticle()  

  4.     {  

  5.         User u = new User();  

  6.         u.setName("張鴻洋");  

  7.         new UserDao(getContext()).add(u);  

  8.         Article article = new Article();  

  9.         article.setTitle("ORMLite的使用");  

  10.         article.setUser(u);  

  11.         new ArticleDao(getContext()).add(article);  

  12.   

  13.     }  

  14.   

  15.     public void testGetArticleById()  

  16.     {  

  17.         Article article = new ArticleDao(getContext()).get(1);  

  18.         L.e(article.getUser() + " , " + article.getTitle());  

  19.     }  

  20.   

  21.     public void testGetArticleWithUser()  

  22.     {  

  23.   

  24.         Article article = new ArticleDao(getContext()).getArticleWithUser(1);  

  25.         L.e(article.getUser() + " , " + article.getTitle());  

  26.     }  

  27.       

  28.     public void testListArticlesByUserId()  

  29.     {  

  30.   

  31.         List<Article> articles = new ArticleDao(getContext()).listByUserId(1);  

  32.         L.e(articles.toString());  

  33.     }  


分別測試,添加一個Article;經過Id獲取一個Article;經過Id獲取一個Article且攜帶User;經過userId獲取全部的Article;

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

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

兩種方式:

一、即上述寫法

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. article = articleDaoOpe.queryForId(id);  

  2.             helper.getDao(User.class).refresh(article.getUser());  


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

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


四、關聯一個集合

每一個User關聯一個或多個Article,若是我在User中聲明一個Collection<Article> articles,我可否在查詢User的時候,一併可以獲取到articles的值呢?

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

@ForeignCollectionField
private Collection<Article> articles;

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

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public User get(int id)  

  2.     {  

  3.         try  

  4.         {  

  5.             return userDaoOpe.queryForId(id);  

  6.         } catch (SQLException e)  

  7.         {  

  8.             e.printStackTrace();  

  9.         }  

  10.         return null ;  

  11.     }  


測試代碼:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public void testGetUserById()  

  2.     {  

  3.         User user = new UserDao(getContext()).get(1);  

  4.         L.e(user.getName());  

  5.         if (user.getArticles() != null)  

  6.             for (Article article : user.getArticles())  

  7.             {  

  8.                 L.e(article.toString());  

  9.             }  

  10.     }  

輸出:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. 09-07 22:49:06.484: E/zhy(7293): 張鴻洋  

  2. 09-07 22:49:06.484: E/zhy(7293): Article [id=1, title=ORMLite的使用]  

能夠看到,咱們經過一個queryForId,成功的獲取了User,以及User關聯的全部的Articles;


五、條件查詢QueryBuilder的使用

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

一、簡單的where等於

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

二、where and 

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. QueryBuilder<Article, Integer> queryBuilder = articleDaoOpe  

  2.                 .queryBuilder();  

  3.         Where<Article, Integer> where = queryBuilder.where();  

  4.         where.eq("user_id"1);  

  5.         where.and();  

  6.         where.eq("name""xxx");  

  7.   

  8.         //或者  

  9.         articleDaoOpe.queryBuilder().//  

  10.                 where().//  

  11.                 eq("user_id"1).and().//  

  12.                 eq("name""xxx");  


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

三、更復雜的查詢

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. where.or(  

  2.                     //  

  3.                     where.and(//  

  4.                             where.eq("user_id"1), where.eq("name""xxx")),  

  5.                     where.and(//  

  6.                             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' )  ;

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

六、updateBuilder、deleteBuilder

使用queryBuilder是由於咱們但願執行完成查詢直接返回List<Bean>集合;

對於Update咱們並不關注返回值,直接使用

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

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

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

七、事務操做

在咱們的Dao中直接寫以下代碼:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. //事務操做  

  2.         TransactionManager.callInTransaction(helper.getConnectionSource(),  

  3.                 new Callable<Void>()  

  4.                 {  

  5.   

  6.                     @Override  

  7.                     public Void call() throws Exception  

  8.                     {  

  9.                         return null;  

  10.                     }  

  11.                 });  



八、其餘操做

一、當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會報錯,尼瑪,我以爲一點用沒有。。。

二、Join

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. QueryBuilder<Article, Integer> articleBuilder = articleDaoOpe  

  2.                     .queryBuilder();  

  3.             QueryBuilder userBuilder = helper.getDao(User.class).queryBuilder();  

  4.             articleBuilder.join(userBuilder);  


Article與User作Join操做;


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



源碼點擊下載

相關文章
相關標籤/搜索