6 - Sqlite - Lce

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 33

Développement Mobile

sous Android
6 – Les baes de données SQLite

Chargé de cours : Faten Abbassi


FST – 2019/2020
Rappels
• A quoi servent les fichiers de ressources XML ?
• Définir les adaptateurs Android et donner leur rôle.
• Citer quelques exemples d’adaptateurs.
• Donner les principaux évènements dans le cycle de
vie d’une activité
• Quelle est l’utilité de la méthode onCreate de la
classe Activity?

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.

• Certaines fonctionnalités standard de SQL ne sont pas reconnues par


SQLite, notamment les contraintes FOREIGN KEY, les transactions
imbriquées, RIGHT OUTER JOIN, FULL OUTER JOIN et certaines
variantes de ALTER TABLE.

• Contrairement à d’autres SGBD (exemple: MySQL), SQLite ne


nécessite pas de serveur pour fonctionner.

• SQLite fournit une interface SQL tout en offrant une empreinte


mémoire très réduite et une rapidité de traitement satisfaisante. 241
Présentation de SQLite

• 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.

• SQLite est efficace en terme de mémoire que le moteur d’exécution


d’Android peut l’inclure dans son intégralité.

• Chemin de stockage des bases de données par défaut


/data/data/<espace de noms>/databases

• Le fichier de bases de données est automatiquement créé en


MODE_PRIVATE, par conséquent les bases ne sont accessibles qu'au
sein de l'application elle-même.
242
Typage manifeste
• La plus grosse différence avec les autres SGBDR concerne principalement le typage
des données (appelé typage manifeste).

• 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.

• Pour SQLite, il n'existe que cinq types de données :


– NULL pour les données NULL.
– INTEGER pour les entiers (sans virgule).
– REAL pour les nombres réels (avec virgule).
– TEXT pour les chaînes de caractères.
– BLOB pour les données brutes.

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.

• Trois méthodes sont nécessaires:


– Un constructeur qui appelle celui de sa classe parente et qui prend en paramètre le
Context (une Activity), le nom de la base de données, une éventuelle fabrique de
curseur (le plus souvent, ce paramètre vaudra null) et un entier représentant la version
du schéma de la base.
– onCreate, prend en paramètre l’objet SQLiteDatabase qui sera rempli avec les tables et
les données initiales. C'est dans cette méthode qu’on doit lancer les instructions pour
créer la base et éventuellement la remplir avec des données.
– onUpgrade, reçoit un objet SQLiteDatabase ainsi que l’ancien et le nouveau numéro de
version. Pour convertir une base d’un ancien schéma à un nouveau, l’approche la plus
simple consiste à supprimer les anciennes tables et à en créer de nouvelles. 244
Conception d’une base de
données SQLite
Exemple de classe d’aide SQLiteOpenHelper

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

• La méthode onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) est


déclenchée à chaque fois que l'utilisateur met à jour son application.

• 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.

• Ce modèle de conception est appelé adaptateur.

• Les requêtes et les actions de mise à jour sont encapsulées dans l’adaptateur.

• Cette organisation implique d'utiliser deux classes :


– Une classe qui représente les informations et qui peut contenir un enregistrement d'une table
(exemple: classe Formation pour représenter une ligne de la table Formation).
– Une classe contrôleur qui effectuera les opérations sur la base

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.

• Exemple: interroger une table système de SQLite (sqlite_master) pour savoir si la


table « Formation » existe déjà.
Cursor c=db.rawQuery("SELECT name FROM sqlite_master WHERE type=’table’
AND name=‘Formation’", null);

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.

• La méthode query retourne un curseur permettant ensuite de


naviguer dans les résultats.

• 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.

• Syntaxe en utilisant While:


while (cursor.moveToNext()) {
// instructions
}
cursor.close();

• Syntaxe en utilisant for:


for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
// instructions
}
cursor.close(); 255
Exemple de parcours et d’extraction
de valeurs d’un curseur
• Pour récupérer les données des différentes formations depuis un curseur, il
suffit de naviguer au sein de celui-ci, puis utiliser l’une des méthodes
getInt(), getString(), getFloat(), etc. pour retrouver la valeur à partir de
l’index de la colonne.

• 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.

• Les ContentValues sont utilisés pour insérer des données dans la


base.
– ContentValues valeurs =new ContentValues();
– valeurs.put("codeF", "inf7");
– valeurs.put("nomF", "Android");
– valeurs.put("duree", 40);
– valeurs.put("niveau", 1);
– db.insert("Formation", getNullColumnHack(), valeurs );

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.

• Exemple: Mettre à jour la durée d’une formation


– ContentValues valeurs =new ContentValues();
– valeurs.put("duree", 50);
259
– Db.update("Formation", valeurs, "codeF = "+F);
Supprimer des données
• Pour supprimer des données d’une table, la méthode delete de la classe
SQLiteDatabase spécifie le nom de la table ciblée et le critère permettant à la base
d’identifier les éléments à supprimer.

• Syntaxe: int delete(String table, String whereClause, String[] whereArgs).

• La méthode update() prend en paramètre:


– le nom de la table,
– Une clause correspondant au WHERE dans SQL,
– une clause WHERE et une liste de paramètres (tableau des valeurs ) qui remplaceront les
marqueurs (?) présents dans celle-ci.
• L'entier renvoyé est le nombre de lignes supprimées.

• Exemple: Supprimer les formations du niveau 3 et ayant une durée supérieure à 30


– String [] args = {"30", "3"};
– db.delete(Formation, "duree > ? AND niveau = ?", args);
260
Clients SQLite
• Il est possible d’utiliser un client graphique pour SQLite pour manipuler le contenu
d’une base de données (exemple: l’extension SQLite Manager pour Firefox). Il suffit
de copier la base du terminal mobile sur la machine de développement.

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.

• Pour exposer les données d’une base de données particulière à d’autres


applications, il faut utiliser un fournisseur de contenu.

• Les curseurs sont des objets qui fonctionnent comme les tableaux.

• Une bonne pratique et de définir des permettant de transformer le curseur de


résultat en objet métier (exemple: méthodes cursorToFormation).

• 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

Vous aimerez peut-être aussi