2013-12-20 8 views
14

SQLiteOpenHelperから派生した私のクラスは、一度に大きくなりました。発言時には、それは涼しいとはみなされない1500行以上のコードです。それが成長することを防ぐための、すなわちピースごとの分離を行うためのエレガントな解決策がいくつかあります。それらのものが何であるかはっきりしない。上記のクラスから継承することは悪い習慣であると言う人もいます。誤動作がデータベースの作成/アップグレード手順につながるからです。何かヒント?どうもありがとう!SQLiteOpenHelperから派生したクラスが巨大になっています

+0

公式カレンダプロバイダまたは連絡先プロバイダのSQLiteOpenHelpersを見てください:-) 'ContactsDatabaseHelper'の' onUpdate() 'メソッドは約900行です - 他のメソッドに関連するバージョンの変更を委任してください。しかし、彼らはバージョン番号800です!クラス全体は約5000行のコードです。だからあなたはあまりにも残念に感じるべきではありません:-)もっと真剣に:IMHO ** 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); 

    } 

その後、私は各テーブルの実装をコーディングします。一般的なtipe Eは通常pojosです。注意データを保持するだけのクラス(pojos)と持続的なデータ(DAO)のクラスを混在させるわけではありません。たとえば、pojoはその変数(色、年など)とともにCarになります。それから私は、DataAccessObject<Car>を拡張するCarDAOをコード化します。そして、このDAOクラスはpojoの変数をDB列にマッピングし、テーブルを問い合わせてそれに書き込むことを担当します。

最後に、DAOが注入されたSQLiteOpenHelperを作成し、各テーブルの内容をそれらに委譲することができます。これらのDAO実装は、表名と列名の定数を持つ実装です。そして、複雑なクエリのために必要ならば、彼らはお互いに話すことができます。 (これはまた、このアプローチの欠点の1つであることに注意してください。多くのテーブルや列を含むクエリが必要なときは、きちんとしたデザインを作成するのは簡単ではありません。私は与えられたコードスニペットとして従う

+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に移行することです。私は個人的に

下に説明として

  • あなたは、ハイドレーターに基づいて、シンプルでありながら強力なソリューションを使用することができ、私は何を好むことハイドレーター

    これは広く、いくつかのORMで使用される概念であるを使用することですまた、ネイティブのZend Frameworkやその他のシステムでは、データの永続性を提供するために、オブジェクトやWebフォームをデータベースレコードにマッピングして理解しやすく維持する手助けをしています。

    ヒートレーターは、一方のデータベースフィールド名をもう一方のエンティティプロパティにマップするオブジェクトです。この情報は内部的には格納されませんが、データベースからオブジェクトを作成するメカニズムとオブジェクトからデータセットを抽出してデータベースを更新するメカニズムの両方を提供します。
    列名 - >エンティティプロパティの配列を持ち、そのYourClass hydrate()メソッドが呼び出されると、データソースからモデルオブジェクトにそれぞれの情報が転送されます。extract(YourClass yourObject)メソッドyourObjectに含まれているデータを対応するデータベースレコードに転送します

    私はこのアプローチが大好きです。インターフェイスを作成するのは本当に簡単で、一般的な使用例にはいくつかの実装があります。 メインオブジェクトやヘルパーに影響を与えずにデータベース内の変更を実行できます。 また、同じインターフェースを使用してを作成すると、データをjson、xml、残りの呼び出し、またはと想像できるものにエクスポートするためのマッパーを作成できます。

    あなたが良い水分補給業者について考えることができ、継承するクラスをいくつか作成することができれば、本当に小さなデータベースヘルパー、本当に小さなエンティティオブジェクト、一般的な作業を行う抽象クラス、あなたが必要とする可能性があるすべての重量ですが、テーブルやオブジェクトタイプごとに1つのクラスを持つことができるので、それほど多くはありません。したがって、クラスはかなり小さくなりますし、ビジネスレベルで関連するコードのみを含みます。

  • 2

    その後、command pattern

    のようなコマンドクラスでDB操作を実行し、このコマンドをマージするfacade patternを使用することができます(プールのような解放する、またはキャッチ)のみのオープンとクローズのDB接続にシングルトンクラスを考慮することができますより複雑なデータベース操作の実行順序で実行できます。これにより、コードをきれいにして制御しやすくなります。 InsertBookCommandクラスを変更した場合と同様に、関連するすべての操作がその動作によって変更されます。

    を要約すると、私の解決策は次のとおりです。

    オープンDB接続やコマンドにパラメータとしてデシベルを渡します。コマンドを実行します。

    関連する問題