2010-11-20 6 views
18

Meine App verwendet zwei Datenbanken (separate Dateien). Um diese Datenbanken zu behandeln, habe ich zwei Helper-Klassen erstellt, die SQLiteOpenHelper erweitern, einen für jede Datenbank.Android: Kann ich eine SQLiteOpenHelper-Klasse für mehrere Datenbankdateien verwenden?

Ich werde jetzt eine dritte Datenbank hinzufügen und frage mich, ob ich noch eine Helper-Klasse erstellen muss (und wenn ich eine vierte und eine fünfte Datenbank verwenden würde, würde ich noch mehr Helper-Klassen benötigen), oder kann ich das selbe verwenden Helferklasse für mehrere Datenbanken?

Das Problem, das ich mit dem Versuch, nur eine Helper-Klasse zu verwenden, sehe, ist, dass ich nicht sehen kann, wie den Namen der einzelnen Datenbankdateien an den Helper übergeben. Zur Zeit ist der Name der Datenbank fest als ein statisches Feld jeder der Helper-Klassen kodiert, aber wenn ich nur eine Helper-Klasse hätte, müsste ich die verschiedenen Namen an den Konstruktor übergeben können, wenn ich den separaten Helper erstelle Objekte; Das Problem ist, dass der SQLiteOpenHelper-Konstruktor anscheinend von Android mit nur einem Parameter aufgerufen wird: dem Kontext.

+0

Hey Mann! Ich mache etwas sehr ähnliches wie du, aber in meinem Fall brauche ich 2 verschiedene dbHelper-Klassen. Die Sache ist, dass ich einen Fehler bekomme, während ich das versuche. java.lang.IllegalStateException: Die Helper-Klasse war Klasse X, versucht aber, auf die Klasse Y zurückgesetzt zu werden. Warst du jemals mit diesem Problem konfrontiert? – Ajay

Antwort

16

Natürlich können Sie. Es ist nur eine Frage Ihres Helper-Klassen-Designs. Sie können nur den Namen der DB zu Ihrer Helper Klasse Konstruktor übergeben (zusammen mit dem erforderlichen Context Instanz) statt Hardcoding:

public class DBOpenHelper extends SQLiteOpenHelper { 

    public DBOpenHelper(Context context, String dbName, int dbVersion) { 
     super(context, dbName, null, dbVersion); 
    } 
... 
} 
+0

Dumm mich! Ich habe meinen Code zur Codeerstellung von Helper-Objekten nicht korrekt gelesen. Wie du sagst, es ist sehr einfach. – prepbgg

+0

Hallo, ich möchte eine Frage stellen (hoffe es ist nicht zu einfach/offensichtlich), wie iteriert man durch die Helferklasse, um alle Datenbanken zu erstellen? Haben Sie die Hilfsklasse mithilfe einer for-Schleife für die Anzahl der Datenbanken durchsucht, die Sie erstellen möchten, und alle Datenbanknamen übergeben? – jamen

2

Sie benötigen eine abstrakte Klasse, die den hier beschriebenen Upgrade-Prozess implementiert. Dann erweitern Sie diese abstrakte Klasse für jede Ihrer Tabellen. In Ihrer abstrakten Klasse müssen Sie Ihre Tabellen auf eine Weise speichern (Liste, fest codiert), so dass Sie bei der Ausführung von onUpgrade über die Tabellenelemente iterieren und für jedes Tabellenelement die beschriebenen Schritte ausführen. Sie werden selbst aktualisiert und behalten alle ihre vorhandenen Details bei. Beachten Sie, dass das Ereignis onUpgrade nur einmal pro Datenbank ausgelöst wird. Aus diesem Grund müssen Sie alle Ihre Tabellen durchlaufen, um alle zu aktualisieren. Sie behalten nur 1 Versionsnummer über die gesamte Datenbank.

  • begintransaction
  • Lauf eine Tabellenerstellung mit if not exists (wir ein Upgrade durchführen, so dass die Tabelle möglicherweise noch nicht vorhanden ist, wird es nicht ändern und Drop)
  • put in einer Liste die vorhandenen Spalten List<String> columns = DBUtils.GetColumns(db, TableName);
  • Backup-Tabelle (ALTER table " + TableName + " RENAME TO 'temp_" + TableName)
  • neue Tabelle erstellen (das neueste Tabellenerstellung Schema)
  • die Kreuzung mit den neuen Spalten bekommen, diesmal Spalten nehmen n aus der aktualisierten Tabelle (columns.retainAll(DBUtils.GetColumns(db, TableName));)
  • Daten wiederherstellen (String cols = StringUtils.join(columns, ","); db.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s from temp_%s", TableName, cols, cols, TableName)); )
  • entfernen Backup-Tabelle (DROP table 'temp_" + TableName)
  • setTransactionSuccessful

(Dies gilt nicht Tabelle Herabstufung behandeln, wenn Sie eine Spalte umbenennen , die vorhandenen Daten werden nicht übertragen, da die Spaltennamen nicht übereinstimmen.

.

public static List<String> GetColumns(SQLiteDatabase db, String tableName) { 
    List<String> ar = null; 
    Cursor c = null; 
    try { 
     c = db.rawQuery("select * from " + tableName + " limit 1", null); 
     if (c != null) { 
      ar = new ArrayList<String>(Arrays.asList(c.getColumnNames())); 
     } 
    } catch (Exception e) { 
     Log.v(tableName, e.getMessage(), e); 
     e.printStackTrace(); 
    } finally { 
     if (c != null) 
      c.close(); 
    } 
    return ar; 
} 

public static String join(List<String> list, String delim) { 
    StringBuilder buf = new StringBuilder(); 
    int num = list.size(); 
    for (int i = 0; i < num; i++) { 
     if (i != 0) 
      buf.append(delim); 
     buf.append((String) list.get(i)); 
    } 
    return buf.toString(); 
} 
+0

Ich fürchte, das ist zu kompliziert für mich! Vielleicht sollte ich bei mehreren Helper-Klassen für mehrere Datenbanken bleiben. – prepbgg

+0

Sie haben dort alle komplizierten Codefragmente. Sie müssen nur ein für Zyklus einwickeln und wickeln die Transaktion Sachen um. Es gibt kompliziertere Dinge als das. – Pentium10

Verwandte Themen