2013-12-20 21 views
14

SQLiteOpenHelper派生的我的類在一段時間內越來越大。在發言時,超過1500行代碼不被認爲是很酷的。可能有一些優雅的解決方案來防止它的生長,即通過和平分離。不知道那些peaces是什麼。有人說,從提及的類繼承是一種不好的做法,因爲它會導致數據庫創建/升級過程的不當行爲。任何提示?非常感謝!從SQLiteOpenHelper派生的我的類越來越大

+0

您應該查看官方日曆提供程序或聯繫人提供程序的SQLiteOpenHelpers :-)單獨使用ContactsDatabaseHelper的'onUpdate()'方法大約需要900行 - 而將相關的版本更改委託給其他方法。但他們的版本號爲800!整個班級大約有5000行代碼。所以你不應該感到太抱歉:-)更認真:只有onUpgrade()恕我直言**應該隨着時間的推移增長**。沒有其他的! –

回答

11

是的,在dev的示出的例子。網站確實鼓勵創建一個怪物類,在其中硬編碼每個表和列的名稱。這是一團糟。您可能想要創建一個類來處理每個表。這些類可以充當每個表的Data Access Objects

這是我用:

public interface DataAccessObject<E> { 

     public void onCreate(SQLiteDatabase db); 

     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion); 

     public void create(E... params); 

     public E[] retrieve(E... params); 

     public void update(E... params); 

     public void delete(E... params); 

    } 

然後我的代碼爲每個表的實現。通用的T E通常是pojos。注意我沒有將用於保存數據的類(pojos)與負責持久檢索數據的類(DAO)混合起來。例如pojo可以是Car,其變量(顏色,年份等)。然後我會編寫一個擴展爲DataAccessObject<Car>的CarDAO。這個DAO類負責將pojo的變量映射到數據庫列,查詢表格並寫入它。

最後,您可以擁有一個與DAO一起注入的SQLiteOpenHelper,並將每個表的內容委託給它們。這些DAO實現是具有表和列名稱常量的實現。如果需要進行一些複雜的查詢,他們可以相互交談。 (注意這也是這種方法的一個缺點:當你需要涉及許多表和列的查詢時,生成一個整潔的設計並不簡單)。

+1

完全同意(幾乎)。不過,我不確定我是否有基於表格的分離度。我會將它基於域對象(實際上可能與表相同)。 +1這個答案。 – Nick

6

你的幫手不需要那麼大。我只能假設你將操縱數據的所有代碼放到你的助手中。

您應該將代碼放在與其相關的類中,並且可以以面向對象的方式訪問它。

例如如果您有聯繫人類別。您會將保存聯繫人的代碼放入數據庫中。

See my post here

6

我按照給出的代碼片段:

提供SQLHelper類:

public class SQLHelper extends SQLiteOpenHelper { 
     public SQLHelper(Context context, String DBName) 
     { 
      super(context, DBName, null, DATABASE_VERSION); 
     } 

     public SQLiteDatabase getDBObject(int isWrtitable) 
     { 
      return (isWrtitable == 1) ? this.getWritableDatabase() : this.getReadableDatabase(); 
     } 

     @Override 
     public void onOpen(SQLiteDatabase db) 
     { 
      super.onOpen(db); 
      onCreate(db); 
     } 

     @Override 
     public void onCreate(SQLiteDatabase db) 
     { 

      db.execSQL(TABLE_1); 
      db.execSQL(TABLE_2); 
      ... 
      db.execSQL(TABLE_N); 
     } 
    } 

MySQLManager:哪個做的大部分工作:

public class MySQLManager 
    { 
     private SQLHelper sqlHelper; 

     //Singlton class 

     public void initMySQLManager(Context context, String DBName) 
     { 
      _context = context; 
      sqlHelper = new DBHandler(context, DBName); 
     } 


     public MyObject getMyObjectRecord() { 
      MyObject myObj = new MyObject(); 
      Cursor cursor = null; 

      try { 
       cursor = dbObject.getWritableDatabase().rawQuery("select * FROM " + SQLHelper.MYOBJECT_TABLE + ";", null); 
       //fetch things 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } finally { 
       if (cursor != null && !cursor.isClosed()) { 
        cursor.close(); 
       } 
      } 
      return bookVo; 
     } 

     //Similarly other methods. 
    } 
8

你應該避免把所有型號的特定代碼你可以幫助你的幫手。把它想象成你可以在下一個項目中儘可能地重用的東西。您可以按照您將會看到的一些常見數據抽象模式和原則進行操作。

  • 例如,你可以想想Active Record,你有你的業務對象,其屬性和方法,以及所有相關的持久性(讀取和寫入數據庫)的方法。另外,您可以考慮輕量級對象,並將實例保存到數據庫中,並通過其他一些提供映射功能的對象(如一些ORM所做的實體管理器)從數據庫中檢索它們。
  • 你也可以看看Zend TableGateway,它是一種很酷的方法來將數據庫表格表示爲對象,並將其遷移到android和sqlite。
  • 您可以使用基於hydrators一個簡單而強大的解決方案,因爲我下面

個人解釋,我寧願是用Hydrators

這是廣泛應用於一些ORM概念,也可以在原生的Zend Framework中,並在其他系統中提供數據持久性,這是爲了幫助對象甚至web表單以易於理解和維護的方式映射到數據庫記錄。

水化器是一種將數據庫字段名稱映射到實體屬性的對象。它不會在內部存儲此信息,但會提供從數據庫創建對象的機制,以及從對象中提取數據集以更新數據庫的機制。
是什麼東西可以像使用列名稱 - >實體屬性數組的對象一樣簡單地啓動,並且在調用YourClass hydrate()方法時,會將各自的信息從數據源傳輸到模型對象,並且當extract(YourClass yourObject)方法被調用時,它將包含在yourObject中的數據傳輸到相應的數據庫記錄

我非常喜歡這種方法,因爲創建接口非常簡單,並且常見用例有多個實現。 因此,您可以在不影響主對象或助手的情況下對數據庫執行更改。 此外,使用相同的接口,您可以創建映射器,將您的數據導出到json,xml,休息調用或任何您可以想象的其他東西

如果你可以考慮一個好的水化器設計,然後創建一些類來繼承,你可以有一個非常小的數據庫幫助器,真正的小實體對象,一些抽象類來做共同的工作,以及一些具體的水化器,可以得到所有你可能需要的權重,但從來沒有那麼多,因爲你可以爲每個表或對象類型都有一個,所以這些類明顯更小,而且它們只包含在業務級別相關的代碼。

2

你可以考慮一個單獨的類只有打開和關閉數據庫連接(或掛鉤,釋放出像池),然後在command pattern

執行與命令類的數據庫操作,比如你也可以使用facade pattern合併這個命令在更復雜的數據庫操作執行順序。這將使您的代碼乾淨,容易控制。比如當你改變你的課程時,所有相關的操作都會因爲它而改變其行爲。

綜上所述,我的解決辦法是:

打開分貝連接並傳遞分貝作爲參數的命令。然後執行這些命令。