乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      JAVAME的RMS通用持久化框架 - 千里冰封 - BlogJava

       suweixin 2011-01-15
      在寫JAVAME程序的時候,我們經(jīng)常需要保存一些數(shù)據(jù)到手機里面,也經(jīng)常希望能把對象也保存到手機里面,但是JAVAME里面沒有反射機制,也沒有java.io.Serializable接口,所以沒有序列化的機制,要保存對象的話,就得自己動手了。
      在JAVAME中,程序的數(shù)據(jù)保存的地方,無外乎兩種,一種是把數(shù)據(jù)保存在RMS里面,這是所有的JAVAME的手機都支持的,還有一種就是把數(shù)據(jù)保存在手機的文件系統(tǒng)里面,這個不是所有手機都能支持的,只有支持JSR075的手機,才支持把數(shù)據(jù)保存在文件系統(tǒng)里面,并且如果你的程序沒有經(jīng)過簽名的話,你每次保存或者讀取,手機都會彈出惱人的提示,是否允許程序訪問文件系統(tǒng)。所在我一般都是把數(shù)據(jù)存在RMS里面,因為讀寫RMS是安全的,并且也是不需要手機提示的。因為我們的RMS數(shù)據(jù)是存在一個特殊的地方。但是JAVAME的RMS功能非常底層,為了保存一些數(shù)據(jù),我們必須和byte[]打交道,所以我就產(chǎn)生了,在此之前封裝一層自己的程序的想法,這樣封裝好以后,使用起來就非常方便了。只要實現(xiàn)了相關接口,就可以享受到比較易用的方法了。

      此框架總共包括了四個類,分別如下:
      Serializable類,它是一個接口,類似于JAVASE里面的Serializable接口,唯一不同的就是,JAVASE里面的接口是一個空接口,只做標記用的,而這里的這個接口是有方法需要實現(xiàn)的。
      Lazy類,它也是一個接口,它定義了一些方法,如果你的對象比較大,需要惰性加載的時候,可以實現(xiàn)此接口,并且此接口是Serializable接口的子類,也就是說實現(xiàn)了Lazy接口,你就相當于實現(xiàn)了Serializable接口。
      RMSUtil類,此類是一個工具類,用于統(tǒng)一進行RMS的相關操作,也是此框架的核心類。
      RecordFetcher類,也是一個接口,它繼承了RecordComparator, RecordFilter接口,在取數(shù)據(jù)的時候,需要用到它。

      好了,下面我們就開始看代碼吧。

       1 /*
       2  * To change this template, choose Tools | Templates
       3  * and open the template in the editor.
       4  */
       5 package com.hadeslee.mobile.rms;
       6 
       7 import java.io.IOException;
       8 
       9 /**
      10  * 一個可自己串行化的類所要實現(xiàn)的接口
      11  * @author hadeslee
      12  */
      13 public interface Serializable {
      14 
      15     /**
      16      * 把自己編碼成字節(jié)數(shù)組的格式
      17      * @return 字節(jié)數(shù)組
      18      */
      19     public byte[] serialize() throws IOException;
      20 
      21     /**
      22      * 把一個對象用此字節(jié)數(shù)組進行重裝
      23      * @param data 字節(jié)數(shù)組
      24      */
      25     public void unSerialize(byte[] data) throws IOException;
      26 
      27     /**
      28      * 設置此對象序列化后對應的存儲對象的ID
      29      * @param id ID
      30      */
      31     public void setId(int id);
      32 
      33     /**
      34      * 得到此對象序列化后的ID
      35      * 此方法唯有在反序列化后的對象上調(diào)用才有效
      36      * 如果一個對象是沒有序列化的,那么它的ID是-1;
      37      * @return ID
      38      */
      39     public int getId();
      40 }
      41 

       1 /*
       2  * To change this template, choose Tools | Templates
       3  * and open the template in the editor.
       4  */
       5 package com.hadeslee.mobile.rms;
       6 
       7 import java.io.IOException;
       8 
       9 /**
      10  * 可以延遲加載的對象必須要實現(xiàn)的接口
      11  * @author binfeng.li
      12  */
      13 public interface Lazy extends Serializable {
      14 
      15     /**
      16      * 實現(xiàn)此接口的類要實現(xiàn)的方法
      17      * 可以用于延遲加載某些屬性。比如
      18      * get("ImgData"),get("fullImage")..等等
      19      * 由于J2ME不支持注釋也不支持反射,所以只能以
      20      * 此種方法來進行模擬了
      21      * 此方法是RMSUtil要存對象的時候調(diào)用的,這樣就可以把
      22      * 一個對象的不同部份存到不同的RMS里面去了
      23      * @param key 要得到的某性的鍵
      24      * @return 其對應的值
      25      * @throws IOException 
      26      */
      27     public byte[] getAttach(Object key)throws IOException;
      28 
      29     /**
      30      * 當把某個附屬的對象保存進去以后,所要調(diào)用的
      31      * 方法,此方法告訴主體,它的那個附件被保存后
      32      * 在RMS里面對應的ID是多少
      33      * @param key
      34      * @param id
      35      */
      36     public void savedAttach(Object key, int id);
      37 
      38     /**
      39      * 得到此對象所支持的所有的key的數(shù)組
      40      * @return KEY的數(shù)組,不能為NULL
      41      */
      42     public Object[] getAttachKeys();
      43 
      44     /**
      45      * 此對象的附屬對象所存的RMS的名字
      46      * @return RMS的名字
      47      */
      48     public String getNameOfAttachRMS();
      49 }
      50 

       1 /*
       2  * To change this template, choose Tools | Templates
       3  * and open the template in the editor.
       4  */
       5 package com.hadeslee.mobile.rms;
       6 
       7 import javax.microedition.rms.RecordComparator;
       8 import javax.microedition.rms.RecordFilter;
       9 
      10 /**
      11  * 此類是一個繼承了兩個接口的接口,并且添加了自己
      12  * 的方法,自己的方法是用于通知數(shù)量以及開始取的位置
      13  * 只是為了方便于傳遞參數(shù)以及以后擴展
      14  * @author binfeng.li
      15  */
      16 public interface RecordFetcher extends RecordComparator, RecordFilter {
      17 
      18     /**
      19      * 從哪個下標開始取
      20      * @return 下標
      21      */
      22     public int getFromIndex();
      23 
      24     /**
      25      * 最多取多少條記錄
      26      * @return 記錄
      27      */
      28     public int getMaxRecordSize();
      29 }
      30 

        1 /*
        2  * To change this template, choose Tools | Templates
        3  * and open the template in the editor.
        4  */
        5 package com.hadeslee.mobile.rms;
        6 
        7 import com.hadeslee.mobile.log.LogManager;
        8 import java.util.Enumeration;
        9 import java.util.Hashtable;
       10 import java.util.Vector;
       11 import javax.microedition.rms.RecordEnumeration;
       12 import javax.microedition.rms.RecordStore;
       13 import javax.microedition.rms.RecordStoreException;
       14 
       15 /**
       16  * 一個專門用來操作RMS的工具類,通過這個類
       17  * 可以把RMS封裝起來,上層調(diào)用就更方便了
       18  * @author binfeng.li
       19  */
       20 public class RMSUtil {
       21 
       22     /**
       23      * 用于緩存生命周期之內(nèi)的所有的RecordStore的表,當MIDlet要退出的
       24      * 時候,調(diào)用此類的關閉方法,使RMS正確地被關閉
       25      */
       26     private static Hashtable rmsCache = new Hashtable();
       27 
       28     private RMSUtil() {
       29     }
       30 
       31     /**
       32      * 插入一個對象到一個RMS的數(shù)據(jù)庫里面,如果此數(shù)據(jù)庫不存在
       33      * 則自動創(chuàng)建一個對于MIDlet私有的數(shù)據(jù)庫。如果存在,則直接
       34      * 插在此數(shù)據(jù)庫的最后面
       35      * @param ser 要插入的數(shù)據(jù),必須是實現(xiàn)了Serializable接口的類
       36      * @return 是否插入成功
       37      */
       38     public static boolean insertObject(Serializable ser) {
       39         RecordStore rs = null;
       40         try {
       41             rs = getRecordStore(ser.getClass().getName());
       42             if (ser instanceof Lazy) {
       43                 Lazy lazy = (Lazy) ser;
       44                 insertAttachDatas(lazy);
       45             }
       46             byte[] data = ser.serialize();
       47             int id = rs.addRecord(data, 0, data.length);
       48             ser.setId(id);
       49             return true;
       50         } catch (Exception exe) {
       51             exe.printStackTrace();
       52             LogManager.error("RMSUtil.insertObject(),ser = " + ser + ",exe = " + exe);
       53             return false;
       54         }
       55     }
       56 
       57     /**
       58      * 更新某個對象到RMS里面去,
       59      * @param ser 要更新的對象
       60      * @return 是否成功
       61      */
       62     public static boolean updateObject(Serializable ser) {
       63         RecordStore rs = null;
       64         try {
       65             rs = getRecordStore(ser.getClass().getName());
       66             byte[] data = ser.serialize();
       67             rs.setRecord(ser.getId(), data, 0, data.length);
       68             return true;
       69         } catch (Exception exe) {
       70             exe.printStackTrace();
       71             LogManager.error("RMSUtil.updateObject(),ser = " + ser + ",exe = " + exe);
       72             return false;
       73         }
       74     }
       75 
       76     /**
       77      * 從RMS里面刪除某個對象
       78      * @param ser 要刪除的對象
       79      * @return 是否成功
       80      */
       81     public static boolean deleteObject(Serializable ser) {
       82         if (ser.getId() == -1) {
       83             return false;
       84         }
       85         RecordStore rs = null;
       86         try {
       87             rs = getRecordStore(ser.getClass().getName());
       88             int id = ser.getId();
       89             rs.deleteRecord(id);
       90             ser.setId(-1);
       91             return true;
       92         } catch (Exception exe) {
       93             exe.printStackTrace();
       94             LogManager.error("RMSUtil.deleteObject(),ser = " + ser + ",exe = " + exe);
       95             return false;
       96         }
       97     }
       98 
       99     /**
      100      * 從某個數(shù)據(jù)庫里面讀取某個對象
      101      * @param id 此對象的ID
      102      * @param clz 對應的類
      103      * @return 此對象,如果發(fā)生任何異常,則返回null
      104      */
      105     public static Serializable readObject(int id, Class clz) {
      106         RecordStore rs = null;
      107         try {
      108             rs = getRecordStore(clz.getName());
      109             byte[] data = rs.getRecord(id);
      110             Serializable ser = (Serializable) clz.newInstance();
      111             ser.unSerialize(data);
      112             ser.setId(id);
      113             return ser;
      114         } catch (Exception exe) {
      115             //如果讀取對象失敗,則可能是有東西被刪了或者版本不一樣,此時就應該刪掉
      116             exe.printStackTrace();
      117             LogManager.error("RMSUtil.readObject(),id = " + id + ",Class = " + clz + ",exe= " + exe);
      118             if (rs != null) {
      119                 try {
      120                     rs.deleteRecord(id);
      121                 } catch (Exception ex) {
      122                     ex.printStackTrace();
      123                     LogManager.error("RMSUtil.readObject$rs.deleteRecord(id),id = " + id + ",exe = " + ex);
      124                 }
      125             }
      126             return null;
      127         }
      128     }
      129 
      130     /**
      131      * 得到某個類存在RMS里面的總數(shù),這樣便于分段取
      132      * @param cls 類名
      133      * @return 有效記錄總數(shù)
      134      */
      135     public static int getStoreSize(Class cls) {
      136         try {
      137             RecordStore rs = getRecordStore(cls.getName());
      138             return rs.getNumRecords();
      139         } catch (Exception exe) {
      140             exe.printStackTrace();
      141             LogManager.error("RMSUtil.getStoreSize(),Class = " + cls + ",exe = " + exe);
      142             return -1;
      143         }
      144     }
      145 
      146     /**
      147      * 列出某個類的對象的集合,最多取多少個對象
      148      * @param cls 類名
      149      * @param from 從第幾個開始取
      150      * @param maxSize 最多取多少個對象
      151      * @return 取到的列表
      152      */
      153     public static Vector listObjects(Class cls, int from, int maxSize) {
      154         System.out.println("class="+cls);
      155         if (from < 0 || maxSize < 1) {
      156             throw new IllegalArgumentException("from can not less than 0 and maxSize must greater than 0");
      157         }
      158         Vector v = new Vector();
      159         RecordEnumeration ren = null;
      160         try {
      161             RecordStore rs = getRecordStore(cls.getName());
      162             ren = rs.enumerateRecords(nullnullfalse);
      163             fetchRecord(v, cls, ren, from, maxSize);
      164         } catch (Exception exe) {
      165             LogManager.error("RMSUtil.listObjects(),Class = " + cls + ",from = " + from + ",maxSize = " + maxSize + ",exe = " + exe);
      166             exe.printStackTrace();
      167         } finally {
      168             ren.destroy();
      169         }
      170         return v;
      171     }
      172 
      173     /**
      174      * 用于前面一個方法和后面一個方法的共用方法,
      175      * 它用來從特定的記錄枚舉里面去取特定的記錄,
      176      * 并放到特定的地方
      177      * @param v 要保存的地方
      178      * @param cls 要實例化的類
      179      * @param ren 記錄的枚舉
      180      * @param from 從哪里開始取
      181      * @param maxSize 要取多少條記錄
      182      * @throws java.lang.Exception 可能會拋出的異常
      183      */
      184     private static void fetchRecord(Vector v, Class cls, RecordEnumeration ren, int from, int maxSize) throws Exception {
      185         int index = 0;
      186         int size = 0;
      187         while (ren.hasNextElement()) {
      188             int id = ren.nextRecordId();
      189             if (index >= from) {
      190                 if (size < maxSize) {
      191                     Serializable ser = readObject(id, cls);
      192                     if (ser != null) {
      193                         v.addElement(ser);
      194                         size++;
      195                     }
      196                 } else {
      197                     break;
      198                 }
      199             }
      200             index++;
      201         }
      202     }
      203 
      204     /**
      205      * 列出某個類的對象,并用一種過濾以及排序的方法來進行過濾或者排序
      206      * @param cls 類名
      207      * @param fetcher 取記錄的方法
      208      * @return 記錄列表
      209      */
      210     public static Vector listObjects(Class cls, RecordFetcher fetcher) {
      211         System.out.println("fetcher class="+cls);
      212         int from = fetcher.getFromIndex();
      213         int maxSize = fetcher.getMaxRecordSize();
      214         if (from < 0 || maxSize < 1) {
      215             throw new IllegalArgumentException("from can not less than 0 and maxSize must greater than 0");
      216         }
      217         Vector v = new Vector();
      218         RecordEnumeration ren = null;
      219         try {
      220             RecordStore rs = getRecordStore(cls.getName());
      221             ren = rs.enumerateRecords(fetcher, fetcher, false);
      222             fetchRecord(v, cls, ren, from, maxSize);
      223         } catch (Exception exe) {
      224             LogManager.error("RMSUtil.listObjects(),Class = " + cls + ",exe = " + exe);
      225             exe.printStackTrace();
      226         } finally {
      227             ren.destroy();
      228         }
      229         return v;
      230     }
      231 
      232     /**
      233      * 插入某個可延遲加載的對象的所有附件到數(shù)據(jù)庫里面去
      234      * 插入完成后,此lazy對象將變得很完整,因為此時它的
      235      * 附件對象的ID都已經(jīng)設置好了
      236      * @param lazy 要插入附件的主對象
      237      * @return 是否插入成功
      238      */
      239     private static boolean insertAttachDatas(Lazy lazy) {
      240         try {
      241             Object[] attachKeys = lazy.getAttachKeys();
      242             RecordStore rs = getRecordStore(lazy.getNameOfAttachRMS());
      243             for (int i = 0; i < attachKeys.length; i++) {
      244                 Object key = attachKeys[i];
      245                 byte[] data = lazy.getAttach(key);
      246                 int id = rs.addRecord(data, 0, data.length);
      247                 lazy.savedAttach(key, id);
      248             }
      249             return true;
      250         } catch (Exception exe) {
      251             exe.printStackTrace();
      252             LogManager.error("RMSUtil.insertAttachDatas(),Lazy = " + lazy + ",exe = " + exe);
      253             return false;
      254         }
      255     }
      256 
      257     /**
      258      * 得到某個可以延遲加載的對象的某個附件的字節(jié)數(shù)組內(nèi)容
      259      * TODO 如果能把此方法變成私有,那就更好了
      260      * 此方法是專門供lazy對象調(diào)用的,這樣的話,實體類里面就出現(xiàn)了
      261      * 讀取數(shù)據(jù)的方法,但是由于J2ME不支持反射,只能這樣實現(xiàn)了
      262      * @param lazy 可以延遲加載的對象
      263      * @param id 附件的ID
      264      * @return 對應的數(shù)組
      265      */
      266     public static byte[] getAttachData(Lazy lazy, int id) {
      267         try {
      268             return getRecordStore(lazy.getNameOfAttachRMS()).getRecord(id);
      269         } catch (Exception exe) {
      270             exe.printStackTrace();
      271             LogManager.error("RMSUtil.getAttachData(),Lazy = " + lazy + ",id = " + id + ",exe = " + exe);
      272             return null;
      273         }
      274     }
      275 
      276     /**
      277      * 更新某個對象的附件
      278      * TODO 如果能把此方法變成私有就更好了
      279      * @param lazy 可延遲加載的對象
      280      * @param id 附件的ID
      281      * @param data 附件的內(nèi)容
      282      * @return 是否成功
      283      */
      284     public static boolean updateAttachData(Lazy lazy, int id, byte[] data) {
      285         try {
      286             RecordStore rs = getRecordStore(lazy.getNameOfAttachRMS());
      287             rs.setRecord(id, data, 0, data.length);
      288             return true;
      289         } catch (Exception exe) {
      290             exe.printStackTrace();
      291             LogManager.error("RMSUtil.updateAttachData(),Lazy = " + lazy + ",exe = " + exe);
      292             return false;
      293         }
      294     }
      295 
      296     /**
      297      * 從附件數(shù)據(jù)庫中刪除某個附件
      298      * @param lazy 主對象
      299      * @param id 附件的ID
      300      * @return 是否刪除成功
      301      */
      302     public static boolean deleteAttachData(Lazy lazy, int id) {
      303         try {
      304             RecordStore rs = getRecordStore(lazy.getNameOfAttachRMS());
      305             rs.deleteRecord(id);
      306             return true;
      307         } catch (Exception exe) {
      308             exe.printStackTrace();
      309             LogManager.error("RMSUtil.deleteAttachData(),Lazy = " + lazy + ",id = " + id + ",exe = " + exe);
      310             return false;
      311         }
      312     }
      313 
      314     /**
      315      * 關閉所有的RMS
      316      */
      317     public static void closeAllRMS() {
      318         Enumeration en = rmsCache.elements();
      319         while (en.hasMoreElements()) {
      320             RecordStore rs = (RecordStore) en.nextElement();
      321             closeRecordStore(rs);
      322         }
      323         rmsCache.clear();
      324     }
      325 
      326     public static void deleteRecord(Class cls, int id) {
      327         deleteRecord(cls.getName(), id);
      328     }
      329 
      330     /**
      331      * 刪除某個倉庫里面的某條記錄
      332      * @param rsName 倉庫的名字
      333      * @param id 記錄的ID
      334      */
      335     public static void deleteRecord(String rsName, int id) {
      336         try {
      337             RecordStore rs = RecordStore.openRecordStore(rsName, false);
      338             if (rs != null) {
      339                 rs.deleteRecord(id);
      340             }
      341             rs.closeRecordStore();
      342         } catch (Exception exe) {
      343         }
      344     }
      345 
      346     /**
      347      * 一個簡單的方法用于關閉RecordStore
      348      * @param rs 要關閉的RecordStore
      349      */
      350     private static void closeRecordStore(RecordStore rs) {
      351         try {
      352             rs.closeRecordStore();
      353         } catch (Exception exe) {
      354             LogManager.error("RMSUtil.closeRecordStore(),rs = " + rs + ",exe = " + exe);
      355             exe.printStackTrace();
      356         }
      357     }
      358 
      359     /**
      360      * 得到某個RMS的存儲數(shù)據(jù)庫,先從緩存里面去找,如果沒有找到則生成
      361      * 一個并把它放到緩存里面,還有,因為RMS的名字,最長只支持32位
      362      * @param name 數(shù)據(jù)庫的名字
      363      * @return 找到的RMS數(shù)據(jù)庫
      364      */
      365     private synchronized static RecordStore getRecordStore(String name) throws RecordStoreException {
      366         if (name.length() > 32) {
      367             name = name.substring(name.length()-32, name.length());
      368         }
      369         if (rmsCache.containsKey(name)) {
      370             return (RecordStore) rmsCache.get(name);
      371         } else {
      372             RecordStore rs = RecordStore.openRecordStore(name, true);
      373             rmsCache.put(name, rs);
      374             return rs;
      375         }
      376     }
      377 }
      378 


      相信看完代碼以后,大家應該知道如何使用它吧。如果有需要持久化的類,那么就需要實現(xiàn)Serializable接口,然后只要調(diào)用RMSUtil.insertObject()就可以了,同理,查找也是一樣的,你可以查找同一個類的一系列對象,也可以自己定義記錄查詢器,在里面設置查詢條件。
      目前JAVAME的持久化框架,也有用其它的方法實現(xiàn)的,比如動態(tài)插入代碼的方法,也就是你在寫好了JAVAME的代碼以后,在編譯的過程中,它自動幫你加上相應的方法,我看了一個他們的源碼,其實也就是它們自己幫你實現(xiàn)了一個相當于Serializable接口,我覺得這樣不好的地方在于,它會為你的類添加方法,萬一你的類里面原來就有那個方法的時候,那就會出現(xiàn)不可意料的情況了,還有,我覺得自己的數(shù)據(jù)還是自己一個一個把它寫出來,這樣心里更踏實一些。我一直都認為,封裝得有一個度,不能過度的封裝,過度封裝表面上看是編碼更方便了,但是寫的時候,自己心里也更沒底了,因為你不知道別人的代碼都做了一些什么。因為別人的代碼做的事情太多了。呵呵,純屬個人意見。
      大家如果有什么自己的看法,歡迎留言。
      還有,此代碼用到了我的另外一個通用框架,那就是LOG框架,所以如果直接下載的話,可能會編譯不過了,只要注釋掉LogManager的調(diào)用就可以了。LOG框架的說明點擊這里,這個LOG框架現(xiàn)在正在改動中,以使它更好用,更沒有侵入性。

      Netbeans項目工程打包下載,請點擊這里。此工程中還有LOG框架在里面。


        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多