如何將Android資料庫操作通用化(三)

來源:互聯網
上載者:User

標籤:資料庫操作   資料   android   解決   表名   

      • 概述
      • 悠悠綠水傍林侵日落觀山四望回
      • 幽林古寺孤明月冷井寒泉碧映台
      • 鷗飛滿浦漁舟泛鶴伴閑亭仙客來
      • 遊徑踏花煙上走流溪遠棹一篷開

概述

一個不小心都寫了三篇了,也不知道大家還看得懂不?如果看不懂最好給我留個言,我好下一次改正。

接著上次的說,準備工作都已經做好了,現在咱們就要開始著手解決阻擋Android資料庫操作通用化的五個問題了。

我們先回顧一下問題:
問題1:表名的擷取
問題2:如何將實體中的資料,按照對應關係匯入到資料庫中
問題3:明確實體中主鍵是誰?擷取到主鍵中封裝的值
問題4:如何將資料庫中表的列的資料,按照對應關係,封裝到實體中
問題5:實體的對象建立
悠悠綠水傍林侵,日落觀山四望回。

問題當然是一個一個解決,這樣才有效率,那麼第一個問題來了:表名如何擷取

通常情況下,解決一個問題時,都會以一個方法或者函數開始,這次也不例外,我們先給一個殼子:

/** 問題一:表名的擷取 **/public String getTableName() {    return null;}

一切充滿了希望,也顯得那麼自然。現在我們就要開始思考一些關於如何擷取表名的問題了。

在實際開發中,每一個資料庫表,都會對應著一個具體的實體。就好像news表對應著News類。看看它們,是不是名字好相似?只不過一個是首字母大寫,另一個是全小寫。於是我們心底這麼想,如果我們能夠通過“實體”拿到表名就好了

既然有了路走走看,就知道走的通還是走不通了。

我們可以提出兩個方案:
① 如果能夠擷取到實體,那麼我們就能夠擷取到實體的簡單名稱,然後只需要將首字母小寫就是表名了。但是,這樣的缺點也很明顯,這要求資料庫定義表的名稱和實體的名稱基本一致,這樣就會導致我們定義的實體名稱收到限制。例如:定義了 news表,那麼對應的實體就只能是 News了。
② 利用註解,這樣就可以讓實體的名稱和資料庫表的名稱之間的關係脫離,兩者互不干涉。缺點也是顯而易見,編碼難度增加,(嘿嘿),不過誰叫咱們是有經驗的開發人員,就選這種了。

如果有同學註解遺忘掉了,或者還不是很清晰,可以參看我的這篇文章:http://blog.csdn.net/biezhihua/article/details/43783165

幽林古寺孤明月,冷井寒泉碧映台。

明確了道路,一路向前就可以了。

接下來就要使用到註解和反射什麼的了!!是不是有點小激動~哈哈~

接下來的任務,就是給News實體類增加一個註解了,增加註解的目的則是,將資料庫表和對應實體之間的關係確定下來。請看代碼:

// 註解的作用:將資料庫表和對應的實體確定下來。@TableName(DBHelper.TABLE_NEWS_NAME)public class News {    private int id;    private String title;    private String summary;}

看起來像模像樣的,但是@TableName(DBHelper.TABLE_NEWS_NAME)這句是什嗎? 誰能告訴我?

這句就是我們寫的註解了,但是,此時我們還沒有建立出來,但是不要緊,如果你使用的是Eclipse,請選中這行Ctrl+1,就可以自動建立了,這麼高大上,是不是被震到了!(^ω^)。請看具體的TableName代碼:

/** * 制定了實體和資料庫中表的對應關係 */@Target(ElementType.TYPE) // 指定放置的位置@Retention(RetentionPolicy.RUNTIME) // 指定存活時間public @interface TableName {    /**     * 資料庫中的表名,此處可以存放值     */    String value();}

一切都是這麼簡單明了,讓人心曠神怡。現在,註解已經建立好,實體上的註解也已經添加完畢,並且傳入了表名。接下來在getTableName方法中,繼續填寫代碼就好了。

擷取表名依舊分為兩步:
① 擷取到對象的實體 - 這個是問題五
② 擷取實體頭上的註解,依據value的設定值,確定操作的表。

在虛擬碼的第一步是擷取到對象的實體,經過查看,這個恰好是第五個問題,我們先放著,寫一個空方法來代表。

/** * 問題五:實體物件的建立 */private M getInstance() {    return null;}

具體的getTableName()方法代碼如下所示:

public String getTableName() {    // 虛擬碼:    // ① 問題五:擷取到對象的實體    M m = getInstance();    // ② 擷取實體頭上的註解,依據value的設定值,確定操作的資料庫表    // 需要注意的,想要在“運行時”擷取到註解的資訊,給註解設定存活時間。    TableName tableName = m.getClass().getAnnotation(TableName.class); // annotationType 註解的類型    // 為了安全起見,判斷註解的合法性;合法則返回value值    if (tableName != null) {        return tableName.value();    }    return null;}

有了這個方法,BaseDaoSupport中的delete方法也就可以寫出來了,依舊很簡單,請看代碼:

@Overridepublic int delete(Serializable id) {    return db.delete(getTableName(), DBHelper.TABLE_ID + "=?", new String[] { id.toString() });}

小結:其實呢,在表名的擷取中,我們就是利用註解去解決了一個事,表和實體是一一對應的,它們之間的對應關係是什麼。(TableName)

鷗飛滿浦漁舟泛,鶴伴閑亭仙客來。

是時候表演真正的技術了!!(╰_╯)#

接下來該解決第二個問題了,如何將實體中的資料,按照對應關係匯入到資料庫中。

回想一下第一個問題的解決,其實就是利用註解解決了,表和實體之間的對應關係。以此類推,第二個問題也是要求將實體中的資料,按照對應關係匯入到資料庫中。一樣的思路,繼續往下延續,可以再為實體的欄位一個註解,來體現和資料庫表中列的對應關係。請看代碼:

/** * 制定了實體的子對岸和資料庫表中列的對應關係 */@Target(ElementType.FIELD) // 指定放置的位置@Retention(RetentionPolicy.RUNTIME) // 指定存活時間public @interface Column {    String value();}

只要欄位上有這個註解的,肯定是和資料庫表中的列有對應關係,接下來為實體的欄位添加相應的註解,並傳入列名。請看代碼:

// 註解的作用:將資料庫表和對應的實體確定下來。@TableName(DBHelper.TABLE_NEWS_NAME)public class News {    // 指定了實體和資料庫中表的對應關係    @Column(DBHelper.TABLE_ID)    private int id;    @Column(DBHelper.TABLE_NEWS_TITLE)    private String title;    @Column(DBHelper.TABLE_NEWS_SUMMARY)    private String summary;}

準備工作已經做好了,接下來就要填寫insert中的代碼了,此處建立了一個fillColumn(M m, ContentValues values)方法,把實體M欄位值和欄位上Column(XXX)註解中傳入的列名,用values.put(key,value)方法填入到valeus中,以便insert中填寫資料。代碼如下:

@Overridepublic long insert(M m) {    ContentValues values = new ContentValues();    // m代表資料來源,vlaues是資料匯入的目標    fillColumn(m, values);    return db.insert(getTableName(), null, values);}

代碼很簡單,關鍵在於fillColumn(m, values);的資料填充。通過使用反射技術,擷取到M執行個體的所有欄位集合,再依次拿到每個欄位的值和每個欄位註解的值,並填充到values中,請看代碼:

/** * 問題二:如何將實體中的資料,按照對應關係匯入到資料庫中 *  * @param m 資料來源 * @param values 是資料匯入的目標 */public void fillColumn(M m, ContentValues values) {    // 擷取m上所有的欄位    Field[] fields = m.getClass().getDeclaredFields();    for (Field field : fields) {        // 設定存取權限        field.setAccessible(true);        // 擷取欄位頭上的註解        Column column = field.getAnnotation(Column.class);        if (column != null) {            try {                String key = column.value(); // 擷取註解中,指定的列名                String value = field.get(m).toString(); // 擷取欄位值                // 填寫資料                values.put(key, value);            } catch (IllegalArgumentException e) {                throw new RuntimeException("欄位不屬於m執行個體");            } catch (IllegalAccessException e) {                throw new RuntimeException("沒有訪問欄位域的許可權");            }        }    }}

總結:只要掌握了思路和方法,整潔、清晰的代碼,寫起來也不是那麼困難。

遊徑踏花煙上走,流溪遠棹一篷開。

人生不相見,動如參與商.
今夕複何夕,共此燈燭光.
少壯能幾時,鬢髮各已蒼.
訪舊半為鬼,驚呼熱中腸.
焉知二十載,重上君子堂.
昔別君未婚,兒女忽成行……

如何將Android資料庫操作通用化(三)

聯繫我們

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