2010-11-20 19 views
18

Mon application utilise deux bases de données (fichiers séparés). Pour gérer ces bases de données, j'ai créé deux classes Helper qui étendent SQLiteOpenHelper, une pour chaque base de données. Je vais maintenant ajouter une troisième base de données et je me demande si j'ai besoin de créer une autre classe Helper (et si j'utilise une 4ème et une 5ème base de données aurais-je besoin de plus de classes Helper), ou puis-je utiliser la même Classe d'assistance pour plusieurs bases de données?Android: puis-je utiliser une classe SQLiteOpenHelper pour plusieurs fichiers de base de données?

Le problème que je vois avec essayer d'utiliser une seule classe d'assistance est que je ne vois pas comment passer le nom des fichiers de base de données individuels à l'Aide. Actuellement, le nom de la base de données est codé en dur en tant que champ Statique de chacune des classes Helper, mais si je n'avais qu'une seule classe Helper, je devrais pouvoir transmettre les différents noms au constructeur lors de la création de l'assistant séparé. objets; le problème est que le constructeur SQLiteOpenHelper semble être appelé par Android avec un seul paramètre: le contexte.

+0

Hey man! Je fais quelque chose de très similaire à toi, mais dans mon cas j'ai besoin de 2 classes dbHelper différentes. Chose est que je reçois une erreur en essayant de le faire. java.lang.IllegalStateException: La classe Helper était de classe X mais essaye d'être réinitialisée à la classe Y. avez-vous déjà rencontré ce problème? – Ajay

Répondre

16

Bien sûr, vous pouvez. C'est juste une question de conception de votre classe Helper. Vous pouvez juste passer le nom de DB à votre constructeur de la classe Helper (ainsi nécessaire Context par exemple) au lieu de hardcoding:

public class DBOpenHelper extends SQLiteOpenHelper { 

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

Silly moi! Je ne lisais pas correctement mon code de création de code objet Helper. Comme vous le dites, c'est très simple. – prepbgg

+0

Salut, je voudrais poser une question (j'espère que ce n'est pas trop simple/évident) comment est-ce que vous parcourez la classe d'aide pour créer toutes les bases de données? Avez-vous parcouru la classe d'aide en utilisant une boucle for pour le nombre de bases de données que vous souhaitez créer et transmettre dans tous les noms de bases de données? – jamen

2

Vous avez besoin d'une classe abstraite qui implémente le processus de mise à niveau décrit ici. Ensuite, vous étendez cette classe abstraite pour chacune de vos tables. Dans votre classe abstraite, vous devez stocker vos tables d'une certaine manière (liste, codée en dur). Ainsi, lorsque la fonction onUpgrade se déclenche, vous parcourez les éléments de la table et pour chaque élément de la table, vous suivez les étapes décrites. Ils seront auto-améliorés, en gardant tous leurs détails existants. Notez que l'événement onUpgrade ne se déclenche qu'une seule fois par base de données, c'est pourquoi vous devez parcourir toutes vos tables pour effectuer la mise à niveau de toutes les tables. Vous maintenez seulement 1 numéro de version sur toute la base de données.

  • beginTransaction
  • terme une création de table avec if not exists (nous faisons une mise à niveau, de sorte que le tableau pourrait existe pas encore, il ne parviendra pas modifier et drop)
  • mis dans une liste les colonnes existantes List<String> columns = DBUtils.GetColumns(db, TableName);
  • table de sauvegarde (ALTER table " + TableName + " RENAME TO 'temp_" + TableName)
  • créer un nouveau tableau (le plus récent tableau de schéma de création)
  • obtenir l'intersection avec les nouvelles colonnes, ces colonnes de temps prennent n de la table mis à jour (columns.retainAll(DBUtils.GetColumns(db, TableName));)
  • restaurer les données (String cols = StringUtils.join(columns, ","); db.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s from temp_%s", TableName, cols, cols, TableName)); )
  • table de sauvegarde de suppression (DROP table 'temp_" + TableName)
  • setTransactionSuccessful

(Cela ne gère pas downgrade de table, si vous renommez une colonne , les données existantes ne sont pas transférées car les noms de colonnes ne correspondent pas).

.

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

J'ai peur que ce soit trop compliqué pour moi! Peut-être que je devrais rester avec plusieurs classes Helper pour plusieurs bases de données. – prepbgg

+0

Vous avez tous les fragments de code compliqués là-bas. Vous avez juste à envelopper dans un cycle pour et envelopper les trucs de transaction autour. Il y a des choses plus compliquées que ça. – Pentium10