2013-12-20 2 views
14

Meine Klasse, die von SQLiteOpenHelper abgeleitet ist, wird im Laufe der Zeit immer größer. Zur Redezeit sind es mehr als 1500 Codezeilen, die nicht als cool angesehen werden. Es könnte eine elegante Lösung geben, um zu verhindern, dass sie wächst, d. H. Durch Stücke getrennt wird. Nicht sicher, was diese Stücke sein sollen. Einige Leute sagen, dass es eine schlechte Übung ist, von der erwähnten Klasse zu erben, weil dies zu einem Fehlverhalten bei der Erstellung/Aktualisierung von Datenbanken führt. Irgendein Hinweis? Danke vielmals!Meine von SQLiteOpenHelper abgeleitete Klasse wird sehr groß

+0

Sie sollten sich die SQLiteOpenHelper des offiziellen Kalenderanbieters oder des Kontaktanbieters ansehen :-) Die 'onUpdate()' Methode von 'ContactsDatabaseHelper' alleine ist ungefähr 900 Zeilen lang - während sie relevante Versionsänderungen an andere Methoden delegiert. Aber sie sind bei der Versionsnummer 800! Die Klasse insgesamt umfasst etwa 5000 Zeilen Code. Also sollte es dir nicht so leid tun :-) Ernsthafter: IMHO ** onlyUpgrade() sollte mit der Zeit immer größer werden **. Nichts anderes! –

Antwort

11

Ja, die Beispiele in der dev gezeigt. ermutigen Sie die Erstellung einer Monsterklasse, in der Sie die Namen aller Tabellen und Spalten fest codieren. Das ist ein Chaos. Möglicherweise möchten Sie eine Klasse erstellen, um jede Tabelle zu behandeln. Diese Klassen können als Data Access Objects für jede Tabelle fungieren. Diese

ist das, was ich benutze:

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); 

    } 

Dann für jede Tabelle eine Implementierung I codieren. Die generischen tipe E sind in der Regel pojos. Beachten Sie, dass ich die Klassen, die nur dazu dienen sollen, Daten (pojos) zu speichern, nicht mit den Klassen mischen, die für das persistierende Abrufen von Daten (DAOs) zuständig sind. Zum Beispiel könnte ein Pojo Car mit seinen Variablen (Farbe, Jahr, etc) sein. Dann würde ich einen CarDAO codieren, der DataAccessObject<Car> verlängert. Und diese DAO-Klasse ist dafür verantwortlich, die Variablen des Pojos DB-Spalten zuzuordnen, die Tabelle abzufragen und darauf zu schreiben.

Schließlich können Sie eine SQLiteOpenHelper haben, die mit den DAOs injiziert wird, und delegiert Zeug für jede Tabelle an sie. Diese DAO-Implementierungen haben die Namen von Tabellen- und Spaltennamen. Und sie können miteinander reden, wenn sie für komplexe Anfragen benötigt werden. (Beachten Sie, dass dies auch einer der Nachteile dieses Ansatzes ist: Das Erstellen eines übersichtlichen Designs ist nicht einfach, wenn Sie Abfragen mit vielen Tabellen und Spalten benötigen).

+1

Stimme (fast) vollständig zu. Ich bin mir nicht sicher, ob die Trennungsgrade auf Tabellen basieren.Ich würde es stattdessen auf die Domain-Objekte basieren (die in der Tat die gleichen wie die Tabellen sein können, hängt ab). +1 auf diese Antwort. – Nick

6

Ihr Helfer sollte nicht so groß sein. Ich kann nur annehmen, dass Sie allen Code, der Daten manipuliert, in Ihren Helper stecken.

Sie sollten Code in die Klasse einfügen, auf die er sich bezieht und auf die Sie objektorientiert zugreifen können.

z. B. Wenn Sie eine Klasse Kontakte haben. Sie würden Code, der einen Kontakt gespeichert hat, in die Datenbank einfügen.

See my post here

6

ich als gegeben Code-Schnipsel folgen:

SQLHelper Klasse:

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: Welche meiste Arbeit macht:

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

Sie vermeiden sollten alle modellspezifischen Code setzen in dein Helfer wie du kannst. Denken Sie darüber nach, dass Sie im nächsten Projekt so viel wie möglich wiederverwenden können. Sie können einige der gängigen Datenabstraktionsmuster und -prinzipien befolgen, die Sie sehen werden.

  • Zum Beispiel können Sie darüber nachdenken, Active Record, wo Sie Ihre Business-Objekte haben, mit seinen Feldern und Methoden, und auch all Verfahren zum persistance bezogenen (lesen und aus der Datenbank schreiben).
  • Sie können auch über ein leichtgewichtiges Objekt nachdenken und Instanzen speichern und von der Datenbank durch ein anderes Objekt abrufen, das Mapping-Funktionen bietet, wie z. B. ORMs.
  • Sie können auch einen Blick auf Zend TableGateway werfen, dass es ein cooler Ansatz für die Darstellung von Datenbanktabellen als Objekte, die Sie auf Android und SQLite migrieren.
  • Sie eine einfache und dennoch leistungsfähige Lösung auf hydrators Basis verwenden kann, wie ich weiter unten

persönlich erklären, ich ziehe, was hydrators

Dies ist ein Konzept weit verbreitet in einiger ORM verwendet zu verwenden, , auch in nativem Zend Framework und in anderen Systemen, um Datenpersistenz zu bieten, ist dies, um Objekte oder sogar Webformulare zu Datenbankeinträgen in leicht verständlicher Weise zu verwalten und zu verwalten.

Ein Hydrator ist ein Objekt, das die Datenbankfeldnamen auf der einen Seite den Entitätseigenschaften auf der anderen Seite zuordnet. Es speichert diese Informationen nicht intern, sondern bietet Mechanismen sowohl zum Erstellen von Objekten aus Datenbanken als auch zum Extrahieren von Datensätzen aus Objekten, um die Datenbank zu aktualisieren.
Ist etwas, das so einfach wie ein Objekt mit einem Array von Spaltennamen -> Entity Properties starten kann, und wenn die YourClass hydrate() Methode aufgerufen wird, wird die entsprechende Information aus der Datenquelle auf das Modellobjekt übertragen, und wenn die extract(YourClass yourObject) Methode heißt, es überträgt die in yourObject enthaltenen Daten auf den entsprechenden Datenbankeintrag

Ich mag diesen Ansatz sehr, da es sehr einfach ist, ein Interface zu erstellen, und mehrere Implementierungen für häufige Anwendungsfälle. So können Sie Änderungen in Ihrer Datenbank durchführen, ohne die Hauptobjekte oder den Helper zu beeinflussen. Mit der gleichen Schnittstelle können Sie auch Mapper erstellen, um Ihre Daten in JSON, XML, Ruheanrufe oder andere Dinge zu exportieren, die Sie sich vorstellen können.

Wenn Sie über eine gute Hydrator desing nachdenken und dann einige Klassen erstellen können, können Sie eine wirklich kleine Datenbankhilfe, wirklich kleine Entitätsobjekte, einige abstrakte Klassen, die gemeinsame Arbeit leisten, und einige konkrete Hydratoren, die bekommen können all das Gewicht, das Sie brauchen könnten, aber nie so viel, da Sie für jede Tabelle oder jeden Objekttyp einen haben können. Daher sind die Klassen deutlich kleiner und außerdem enthalten sie nur Code, der geschäftlich verwandt ist.

2

Sie können eine Singleton-Klasse nur öffnen und schließen DB-Verbindung (oder Fang, lassen Sie wie ein Pool) dann das Ausführen der db-Operationen mit Befehlsklasse wie in command pattern

Und Sie können facade pattern verwenden Betrachten Sie diese Befehle fusionieren in einer Ausführungsreihenfolge für komplexere Datenbankoperationen. Dadurch wird Ihr Code sauber und leicht zu kontrollieren. Wenn Sie zum Beispiel Ihre InsertBookCommand Klasse ändern, werden alle damit verbundenen Vorgänge das Verhalten ändern.

Um es zusammenzufassen, meine Lösung ist:

öffnen DB-Verbindung und die DB als Parameter an Befehle übergeben. dann führe die Befehle aus.

Verwandte Themen