<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                在上一篇博客[《打造android ORM框架opendroid(六)——級聯查詢》](http://blog.csdn.net/qibin0506/article/details/43370135)我們講了OpenDroid最后一塊功能查詢的實現原理。今天我們將進行OpenDroid一個重頭戲,也是本系列博客的最后一篇——數據庫升級方案。 說道數據庫升級,我可是很頭疼的, 為什么呢? 因為以前的項目中,根本沒有考慮數據庫升級方案的問題,就直接drop table了,這樣導致的結果就是“以前的數據都消失了”。額。。。 憑空消失確實不是很少的一件事,如果數據不重要還行,重要數據呢? 說消失就消失了? 用戶升級了一下軟件,結果數據全沒了。。。 那是多吊絲的一件事。 OpenDroid則提供了一種數據庫升級的方案,當然這種方案肯定不是完美的。 肯定還有更好的方案,如果你發現你有好的解決方案,請不吝賜教。 好,下面開始進入正題。首先說說我的方案的原理吧:其實很簡單,就是在drop table之前將數據查詢出來,并保存到集合中,在創建新表后,嘗試去insert數據。原理的思路很簡單,以至于我一直認為這種方案太爛了, 可我沒有想到更好的結果方案,也就只能先這樣了。 大家都知道,android的SQLiteOpenHelper類中提供了一個抽象方法onUpgrade()來讓用戶靈活的定制數據庫升級方案, 最簡單的方法就是我之前提到直接drop table。既然upgrade的權利掌握在我們手中,那我們何不借onUpgrade()大干一番呢? 先來看看代碼: ~~~ @Override???? public?void?onUpgrade(SQLiteDatabase?db,?int?oldVersion,?int?newVersion)?{???? ????System.out.println("upgrade?database");???? ????upgrade(db);???? }?? ~~~ 在onUpgrade里除了一句打印,其實真正有用了就一句代碼,當然也是調用了我們自定義的一個方法,那么我們就從upgrade()這個方法開始說起: ~~~ /**?? ?*?升級數據庫?? ?*?@param?db?數據庫鏈接?? ?*/???? private?extends?OpenDroid>?void?upgrade(SQLiteDatabase?db)?{???? ????try?{???? ????????XmlPullParser?pullParser?=?Xml.newPullParser();???? ????????InputStream?inputStream?=?DroidApplication.sContext.getAssets().open("open_droid.xml");???? ????????pullParser.setInput(inputStream,?"utf-8");???? ???????????????? ????????int?type?=?pullParser.getEventType();???? ????????while(type?!=?XmlPullParser.END_DOCUMENT)?{???? ????????????if(type?==?XmlPullParser.START_TAG)?{???? ????????????????//?獲取mapping???? ????????????????if(pullParser.getName().equals(OpenDroidHelper.TAG_MAPPING))?{???? ????????????????????dumpData(db,?pullParser);???? ????????????????}???? ????????????}???? ????????????type?=?pullParser.next();???? ????????}???? ????}?catch?(Exception?e)?{???? ????????e.printStackTrace();???? ????}???? ???????????? ????//?執行創建數據庫???? ????onCreate(db);???? }?? ~~~ 7~9行可以看出我們準備去解析open_droid.xml文件了,和我們平時解析一樣,使用一個while循環,觀察while循環,我們在15~17行獲取到了有用的信息,如果當前的tag是mapping的或,我們又去調用了dumpData,這里面XmlPullParser會作為第二個參數傳遞過去。 方法的最后,我們直接調用了重載的onCreate方法去創建新表,當然還有數據的恢復。這個我們稍后分析,接下來我們來看看dumpData方法。 ~~~ /**?? ?*?將數據庫中的數據轉儲到程序中?? ?*?@param?db?數據庫連接?? ?*?@param?pullParser??? ?*?@throws?Exception?? ?*/???? private?extends?OpenDroid>?void?dumpData(SQLiteDatabase?db,?XmlPullParser?pullParser)???? ????????throws?Exception?{???? ????Class?klass?=?(Class)?Class.forName(pullParser.getAttributeValue(null,?"class"));???? ????String?tableName?=?klass.getSimpleName();?//?表名???? ????Cursor?cursor?=?db.rawQuery("select?*?from?"?+?tableName,?null);???? ???????????? ????T?t;???? ????Method?m;???? ????String?methodName;???? ????String?columnName;???? ???????????? ????//?遍歷游標???? ????for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext())?{???? ????????t?=?(T)?klass.newInstance();??//?通過反射進行實例化???? ????????final?int?columnCount?=?cursor.getColumnCount();???? ????????for(int?i=0;i ????????????columnName?=?cursor.getColumnName(i);?//?獲取字段名???? ????????????//?try一下,如果沒有該字段對應的方法,則消化異常,并繼續???? ????????????try?{???? ????????????????switch?(cursor.getType(i))?{???? ????????????????case?Cursor.FIELD_TYPE_INTEGER:???? ????????????????????methodName?=?columnName.equals("_id")???"setId"?:????? ????????????????????????CRUD.getMethodName(cursor.getColumnName(i));???? ????????????????????m?=?klass.getMethod(methodName,?int.class);?//?反射出方法???? ????????????????????m.invoke(t,?cursor.getInt(i));?//?執行方法???? ????????????????????break;???? ????????????????case?Cursor.FIELD_TYPE_FLOAT:???? ????????????????????methodName?=?CRUD.getMethodName(cursor.getColumnName(i));???? ????????????????????m?=?klass.getMethod(methodName,?float.class);???? ????????????????????m.invoke(t,?cursor.getFloat(i));???? ????????????????????break;???? ????????????????default:???? ????????????????????methodName?=?CRUD.getMethodName(cursor.getColumnName(i));???? ????????????????????m?=?klass.getMethod(methodName,?String.class);???? ????????????????????m.invoke(t,?cursor.getString(i));???? ????????????????????break;???? ????????????????}???? ????????????}?catch?(Exception?e)?{???? ????????????????e.printStackTrace();???? ????????????}???? ????????}???? ????????mOldData.add(t);???? ????}???? ????cursor.close();???? ????db.execSQL("drop?table?if?exists?"?+?tableName);?//?刪除舊的數據庫???? }?? ~~~ 這個方法很長,而且也很關鍵,我們的數據庫升級方案將在這里終結。 第9行,我們通過Class.forName獲取了一個Class, 是根據什么映射呢?來看一下我們open_droid.xml文件就一目了然。 ~~~ open-droid>???? ????version?value="6"?/>???? ????name?value="school"?/>???? ????mapping?class="org.loader.opendroid.Student"?/>???? ????mapping?class="org.loader.opendroid.Grade"?/>???? open-droid>?? ~~~ 這這個xml中,我們就是要通過org.loader.opendroid.Student來映射出一個類。 第10行,我們獲取了該類的類名,當然也就是我們要操作的表名了,唉? 為什么就一個表呢? 仔細看看這個方法是在哪調用的,我們是在一個循環中調用了,也就是在循環中去遍歷xml節點,每次獲取到mapping節點,都來調用一下這個方法。 11行,我們執行一段select語句,將現在表中所有的數據查詢出來,那查詢出來的數據我們怎么處理呢? 要回答這個問題,我們就得去下面的for循環中找答案。 在for循環中,20行,通過反射實例化了上面那個類,為什么要在循環中實例化呢?因為每行數據我們都需要用一個對象來保存。 21行,獲取了當前行所有列的個數。 接下來有一個for循環,這個循環我們是循環的每一行的列,在循環中去取每一列的數據。 26行,進入一個switch語句,依照慣例,我們只去分析一個case語句。 在第一個case中,如果改列的字段是一個integer類型,28行,我們和之前講過的一樣去拼裝一個setter,當然如果是_id的話,我們就直接定義為setId了。 30行,反射出這個方法,等待下面去執行。 當然31行我們就要去執行這個方法了,我們都知道setter方法是需要參數的,參數當然就是我們查詢出來的當前列的數據了。 48行,我們將這個對象的實力放入一個集合中。 當查詢完當前表,這個表就沒用了,因為我們已經把數據都保存起來了,所以在51行,將該表刪除。 至此,我們就把數據從舊版本的數據庫中全部查詢出來了。接下來我們回到onCreate方法中來看看新表是如果創建的,并且數據是如何恢復的。 ~~~ @Override???? public?void?onCreate(SQLiteDatabase?db)?{???? ????for(String?sql?:?OpenDroidHelper.getDBInfoBean().getSqls())?{???? ????????db.execSQL(sql);???? ????}???? ???????????? ????//?還原數據???? ????if(!mOldData.isEmpty())?{???? ????????for(OpenDroid?item?:?mOldData)?{???? ????????????item.save(db);???? ????????}???? ????}???? }?? ~~~ 前面幾行代碼,我們在[《打造android ORM框架opendroid(二)——自動創建數據庫》](http://blog.csdn.net/qibin0506/article/details/42773281)?已經講解過,這里就不重復了,我們重點來看看在那篇博客中省略的幾行代碼,也正是這幾行代碼,實現了舊數據向新表中的轉移。 8行,先去判斷mOldData是否為空的集合,因為onCreate方法并不是只有在數據庫升級的時候才去執行。 接下來遍歷整個集合,并且調用每個item的save方法將數據保存到新表中,當然這里我們重用了OpenDroid類中的save方法,因為都是insert嘛。從這里我們也可以看出這個mOldData集合的泛型肯定是OpenDroid。 `private?ArrayList?mOldData?=?new?ArrayList();??` 好了,至此,我們opendroid提供的一個簡單的數據庫升級方案就執行完了,而且我們的opendroid也介紹的差不多了,剩下的一點東西都是輔助性的東西。哦,對了,這里還要提一點:細心的朋友可能已經發現了,opendroid在操作完數據庫并沒有默認的關閉掉數據庫,而是蛋疼的提供了open和release兩個方法,不信可以看代碼: ~~~ /**?? ?*?打開數據庫?? ?*/???? public?static?void?open()?{???? ????if(sSqliteDatabase?==?null)?{???? ????????sSqliteDatabase?=?sOpenHelper.getWritableDatabase();???? ????}???? }???? ???????? /**?? ?*?釋放數據庫?? ?*/???? public?static?void?release()?{???? ????if(sSqliteDatabase?!=?null?&&?sSqliteDatabase.isOpen())?{???? ????????sSqliteDatabase.close();???? ????}???? ????sSqliteDatabase?=?null;???? }?? ~~~ 這是為什么呢? 其實剛開始我是做了默認關閉了,可就是在寫到數據庫升級恢復數據的時候,因為save是在一個循環中執行了,因此,可能在很短的時間內多次開啟/關閉數據庫,這樣做會消耗很大的性能,所以android會拋出一個異常,在一氣之下,我就將代碼改造成了這種方式,如果有大神有更好的解決方案,請賜教哈。 好了,至此我們opendroid系列博客也就尾聲了,當然,做出一個orm框架本身并不重要,重要的是學會如何去做一個orm框架,別人能做的事,我們為什么就不能呢?對吧,作為一個程序員,我們要努力去做一個“創造者”,而不是簡單停留在一個“使用者”上。 最后是opendroid的開源地址:[http://git.oschina.net/qibin/OpenDroid](http://git.oschina.net/qibin/OpenDroid)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看