2010-11-20 13 views
18

Moja aplikacja wykorzystuje dwie bazy danych (oddzielne pliki). Aby obsłużyć te bazy danych, utworzyłem dwie klasy pomocnicze, które rozszerzają SQLiteOpenHelper, po jednym dla każdej bazy danych.Android: czy mogę użyć jednej klasy SQLiteOpenHelper dla wielu plików baz danych?

Mam teraz zamiar dodać trzecią bazę danych i zastanawiam się, czy potrzebuję stworzyć kolejną klasę Pomocnika (i jeśli użyłbym czwartej i piątej bazy danych potrzebowałbym jeszcze więcej klas Pomocnika), czy mogę użyć tego samego Klasa pomocnika dla wielu baz danych?

Problem, który widzę przy próbie użycia tylko jednej klasy Pomocnika, polega na tym, że nie widzę sposobu przekazania nazwy poszczególnych plików bazy danych do Pomocnika. Obecnie nazwa bazy danych jest zakodowana jako pole statyczne każdej z klas Pomocnika, ale gdybym miał tylko jedną klasę Pomocnika, musiałbym móc przekazywać różne nazwy do Konstruktora podczas tworzenia oddzielnego Pomocnika obiekty; Problem polega na tym, że SQLiteOpenHelper Constructor wydaje się być wywoływany przez Androida z jednym parametrem: Kontekstem.

+0

Hej człowieku! Robię coś bardzo podobnego do ciebie, ale w moim przypadku potrzebuję 2 różnych klas dbHelper. Chodzi o to, że dostaję błąd, próbując to zrobić. Wyjaśnienie java.lang.IllegalStateException: Klasa pomocnicza była klasą X, ale próbuje zostać zresetowana do klasy Y. Czy kiedykolwiek spotkałeś się z tym problemem? – Ajay

Odpowiedz

16

Oczywiście, możesz. To tylko kwestia twojego projektu klasy Helper. Wystarczy podać nazwę DB do konstruktora klasy Helper (wraz z wymaganą Context przykład) zamiast hardcoding:

public class DBOpenHelper extends SQLiteOpenHelper { 

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

Głupi mnie! Nie czytałem poprawnie kodu tworzenia kodu obiektu pomocniczego. Jak mówisz, jest to bardzo proste. – prepbgg

+0

Witam, chciałbym zadać pytanie (mam nadzieję, że nie jest to zbyt proste/oczywiste), w jaki sposób przeprowadzasz iterację w klasie pomocnika, aby utworzyć wszystkie bazy danych? Czy przeglądałeś klasę pomocnika za pomocą pętli for dla liczby baz danych, które chcesz utworzyć i przekazałeś we wszystkich nazwach baz danych? – jamen

2

Potrzebujesz klasę abstrakcyjną, która implementuje opisany tutaj proces aktualizacji. Następnie rozszerzasz tę abstrakcyjną klasę dla każdego ze swoich tabel. W swojej klasie abstrakcyjnej musisz przechowywać tabele w taki sposób (lista, na stałe), więc gdy uruchamiana jest funkcja onUpgrade, będziesz sprawdzać pozycje tabeli i dla każdego elementu tabeli wykonasz opisane kroki. Będą się ulepszać, zachowując wszystkie istniejące szczegóły. Należy pamiętać, że zdarzenie onUpgrade jest uruchamiane tylko raz dla każdej bazy danych, dlatego należy powtórzyć wszystkie tabele, aby dokonać aktualizacji wszystkich z nich. Utrzymujesz tylko 1 numer wersji we wszystkich bazach danych.

  • beginTransaction
  • prowadzony tworem stół z if not exists (robimy upgrade, więc tabela może jeszcze nie istnieje, to nie zmienia i drop)
  • umieszczone w wykazie istniejących kolumn List<String> columns = DBUtils.GetColumns(db, TableName);
  • zapasowej tabeli (ALTER table " + TableName + " RENAME TO 'temp_" + TableName)
  • utworzyć nową tabelę (najnowsza schematu tworzenia tabela)
  • dostać skrzyżowania z nowych kolumn, tym razem wziąć kolumny n z uaktualnionej tabeli (columns.retainAll(DBUtils.GetColumns(db, TableName));)
  • przywracania danych (String cols = StringUtils.join(columns, ","); db.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s from temp_%s", TableName, cols, cols, TableName)); )
  • usuń kopii zapasowej tabeli (DROP table 'temp_" + TableName)
  • setTransactionSuccessful

(To nie obsługuje stół downgrade, jeśli zmienić nazwę kolumny , nie przekazuje się istniejących danych, ponieważ nazwy kolumn nie pasują do siebie).

.

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

Obawiam się, że to dla mnie zbyt skomplikowane! Być może powinienem trzymać się wielu klas Pomocnika dla wielu baz danych. – prepbgg

+0

Masz wszystkie skomplikowane fragmenty kodu. Trzeba tylko zawinąć cykl i zawijać transakcje. Są bardziej skomplikowane rzeczy. – Pentium10

Powiązane problemy