6 - Sqlite - Lce
6 - Sqlite - Lce
6 - Sqlite - Lce
sous Android
6 – Les baes de données SQLite
239
Objectifs de cette partie
• Comprendre le principe de persistance de données
sous Android.
• Etudier les caractéristique des bases de données
SQLite.
• Stocker et manipuler des données dans une base de
données SQLite.
• Concevoir des bases de données SQLite.
• Gérer l'interfaçage avec une base de données à l’aide
d’une couche d’abstraction.
• Réaliser des transitions entre les données et les vues. 240
Présentation de SQLite
• SQLite est une base de données relationnelle légère, gratuite et Open
Source.
• SQLite est un SGBDR complet, avec des triggers, des transactions, etc.
• L’API de SQLite n’est pas JDBC, qui serait trop lourd pour les
terminaux limités en mémoire comme les téléphones.
• Avec le typage manifeste, le type d’une donnée est une propriété de la valeur elle-
même, pas de la colonne dans laquelle la valeur est stockée.
• SQLite permet de stocker une valeur de n’importe quel type dans n’importe quelle
colonne, quel que soit le type déclaré de cette colonne.
243
Conception d’une base de
données SQLite
• Afin de simplifier le code de l’application pour gérer ces opérations, le SDK Android
offre une classe d’aide : SQLiteOpenHelper.
• Cette classe enveloppe tout ce qui est nécessaire à la création et à la mise à jour
d’une base, selon les besoins de l’application.
245
Conception d’une base de
données SQLite
• En utilisant la classe dérivée de SQLiteOpenHelper, si on essaie d’ouvrir une base
alors qu’elle n’existe pas encore, la méthode de callback void
onCreate(SQLiteDatabase db) sera appelée avec le paramètre db qui représentera
la base
• Android rajoute automatiquement dans la base une table qui contient la dernière
valeur connue de la base. À chaque lancement, Android vérifiera la dernière
version de la base par rapport à la version actuelle dans le code.
– Si la version actuelle est plus récente que la dernière version fournie, alors on fait appel à
onUpgrade(SQLiteDatabase, int, int).
– Si la version fournie est plus ancienne, on considère qu'on effectue un retour en arrière et c'est
onDowngrade(SQLiteDatabase, int, int) qui sera appelée.
246
Ouvrir une base de données
• Les méthodes getReadableDatabase et getWritableDatabase permettent
d’obtenir une instance de la base de données respectivement en lecture seule et
en lecture/écriture.
• Exemple:
• Cet appel renverra une instance de SQLiteDatabase qui servira ensuite à interroger
ou à modifier la base de données.
• La méthode close de cette instance permet de libérer la connexion.
• Remarques :
– Avec getWritableDatabase(), si la base ne peut pas être ouverte en écriture, une exception de type
SQLiteException sera lancée.
– pour utiliser la base de données sur un périphérique externe, il faut demander la permission
WRITE_EXTERNAL_STORAGE, sinon la base de données sera en lecture seule.
247
– La méthode boolean isReadOnly permet de savoir si une base de données est en lecture seule.
Accéder à une base de données
• Une manière efficace de gérer l'interfaçage avec une base de données est de
proposer une couche d’abstraction (DAO), afin de proposer des méthodes d’accès
et de manipulation simplifiées à la base.
• Les requêtes et les actions de mise à jour sont encapsulées dans l’adaptateur.
248
Accéder à une base de données
Exemple d’adaptateur
249
Requêtes de sélection
Deux méthodes pour récupérer les données d’une base SQLite : Requêtes brutes ou
requêtes normales.
Requêtes brutes:
• Consiste à utiliser la méthode rawQuery() en lui passant une instruction SELECT.
Cette dernière peut contenir des paramètres positionnels qui seront remplacés par
les éléments du tableau passé en second paramètre.
250
Requêtes de sélection
Requêtes normales:
• consistent à utiliser la méthode query() pour construire une requête à partir des
différentes composantes d’une instruction SELECT.
• À part le nom de la table, les paramètres de la méthode query() peuvent valoir null
lorsqu’ils ne sont pas nécessaires.
251
Requêtes de sélection
• Exemple:
String[] cols={"codeF", "nomF" };
String[] params={"30", "2"};
Cursor result=db.query("Formation", cols, "duree>? AND
niveau=?", params, null, null, null);
• Remarque: Une autre possibilité consiste à utiliser SQLiteQueryBuilder, qui offre
bien plus de possibilités pour construire les requêtes complexes, notamment celles
qui impliquent d’unir les résultats de plusieurs sous-requêtes, par exemple. 252
Utilisation des curseurs pour les
requêtes de sélection
• Toutes les requêtes de sélection SQLite s’effectuent via la méthode
query d’une instance de SQLiteDatabase.
• Les curseurs sont des objets qui contiennent les résultats d'une
recherche dans une base de données.
253
Méthodes de la classe Cursor
Méthode Description
moveToFirst Déplacer le curseur à la première position pour lire les données de la première ligne
moveToLast Déplacer le curseur à la dernière position pour lire les données de la dernière ligne
moveToNext Déplacer le curseur d’une position pour lire la ligne suivante
moveToPrevious Déplacer le curseur d’une position pour lire la ligne précédente
moveToPosition(int) Déplacer le curseur à a position indiquée
getPosition Récupérer la position actuelle dans le curseur
isAfterLast Vérifier si on est après la dernière ligne
getCount Retourne le nombre de lignes qui sont renvoyées par la requête
getColumnName(int) Retourne le nom de la colonne spécifiée par son index
getColumnNames Retourne un tableau de chaine de caractères avec le nom de toutes les colonnes retournées
getInt, getString, … obtenir la valeur d’une colonne donnée de la ligne courante
requery exécuter à nouveau la requête qui a créé le curseur
close libérer les ressources occupées par le curseur 254
Parcourir un curseur
Les méthodes de navigation dans le curseur renvoient des booléens qui valent true si
l'opération s'est déroulée avec succès, ou false auquel cas la ligne demandée
n'existe pas.
• Exemple:
Cursor result=db.rawQuery("SELECT codeF, nomF, Duree, Niveau
FROM Formation");
result.moveToFirst();
while (!result.isAfterLast()) {
int c =result.getString(0);
String n =result.getString(1);
int d =result.getInt(2);
int niv =result.getInt(3);
// Faire quelque chose de ces valeurs...
result.moveToNext();
}
result.close(); 256
Manipuler les données
• Première approche: Utiliser la méthode execSQL()
– Cette méthode permet d’exécuter n’importe quelle instruction SQL qui ne renvoie pas
de résultat (cas de Create, INSERT, UPDATE, DELETE, etc.).
– Exemple:
String req = "INSERT INTO Formation (codeF, nomF, duree, niveau) VALUES (‘inf7’, ‘Android’, 40, 1)";
db.execSQL(req);
• Deuxième approche: utiliser les méthode insert(), update() et delete() sur l’objet
SQLiteDatabase.
– Pour spécifier les valeurs de la ligne à insérer ou à modifier, la méthode accepte un
objet de type ContentValues. Cet objet stocke les valeurs de chaque colonne de la ligne
à insérer ou à modifier sous la forme d’une collection d’associations entre le nom de la
colonne et la valeur.
– La classe ContentValues implémente une interface ressemblant à Map mais avec des
méthodes supplémentaires pour prendre en compte les types de SQLite. Outre get(), qui
permet de récupérer une valeur par sa clé, il y a aussi les méthodes getAsInteger(),
getAsString(), etc.
– L’utilisation de la méthode insert permet de faciliter l’action en proposant une approche
objet.
257
Insérer des données
• La méthode insert() prend en paramètre le nom de la table, celui
d’une colonne pour l’astuce de la colonne nulle et un objet
ContentValues contenant les valeurs à placer dans cette ligne.
258
Mettre à jour des données
• Pour mettre à jour des données dans SQLite, la méthode update de la classe
SQLiteDatabase spécifie un objet ContentValues contenant les nouvelles valeurs et
la valeur de la clause de condition WHERE.
• La méthode update() prend en paramètre:
– le nom de la table,
– un objet ContentValues contenant les colonnes et leurs nouvelles valeurs et,
– une clause WHERE et une liste de paramètres qui remplaceront les marqueurs (?) présents dans
celle-ci.
• La clause WHERE et la liste de paramètres fonctionnent comme les paramètres
positionnels qui existent également dans d’autres API de SQL0
• update() n’autorisant que des valeurs fixes pour mettre à jour les colonnes, vous
devrez utiliser execSQL() si vous souhaitez affecter des résultats calculés.
261
[Source: http://www.sqlitemanager.org]
À retenir
• En fonction de l’application il est utile de mettre en place une série d'opérations
usuelles accessibles à partir d'un DAO.
• Les curseurs sont des objets qui fonctionnent comme les tableaux.
• Afin de gérer au mieux les ressources prises par un Cursor en fonction de l’activité
de l’utilisateur et donc du cycle de vie d’une activité, la classe Activity fournit une
méthode nommée startManagingCursor.
• Lorsque vous n’avez plus besoin de gérer les résultats d’un Cursor, appelez la
méthode stopManagingCursor, puis la méthode close du Cursor pour libérer les
ressources du curseur. 262
Exercice
On désire créer une application permettant de gérer les planètes
stockées dans une base de données SQLite.
1) Créer la classe d’aide GalaxieOpenHelper permettant de créer la
base « Galaxie.db » contenant une table Planete (ID, Nom, Rayon,
Distance).
2) Créer la classe AdaptateurBDPlanete implémentant les méthode
d’accès à la base de données « galaxie.db » et de manipulation de la
table « Planete ».
3) Utiliser la classe SimpleCursorAdapter pour réaliser une liaison
entre la table Planete et une ListActivity.
4) Concevoir les activités permettant d’appeler les différentes
méthodes de consultation, de recherche et de mise à jour des
planètes. 263
Exercice
Aperçu de l’adaptateur:
264
Correction
1) Classe GalaxieOpenHelper
265
Correction
2) Classe d’adaptateur
266
Correction
2) Classe d’adaptateur
267
Correction
2) Classe d’adaptateur
268
Correction
2) Classe d’adaptateur
269
Correction
2) Classe d’adaptateur
270