Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zéro > Les tutoriels > Non-Officiels > Programmation > Autres langages > [AIR] Tout sur Adobe AIR > Réalisation d'une application > Les bases de données locales (partie 1/2) > Lecture du tutoriel

Les bases de données locales (partie 1/2)

Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Avatar
Auteur : K-Phoen
Visualisations : 757

Plus d'informations Plus d'informations
Comme je l'ai annoncé dans le premier chapitre du tuto, AIR met à disposition des applications qu'il fait tourner un système de bases de données locales, et tout ça grâce au moteur open source SQLite.

Ces dernières, parce qu'elles stockent les données dans un fichier (sur le disque dur du PC client, celui qui exécute l'application), sont accessibles même en cas de connexion Internet buggée, ou inexistante. :)
Partant de cela, on imagine très bien pouvoir utiliser ce genre de solution pour :
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Se connecter à une base de données, et la modifier

Se connecter à une base de données



Comme en PHP (par exemple), il est obligatoire de se connecter à la base de données avant de pouvoir effectuer la moindre action sur cette dernière (logique me direz-vous :p ).

La première étape consistera donc à trouver par quel moyen AIR permet à une application d'établir une connexion avec une base de données, et il est important de garder à l'esprit qu'actuellement, nous développons notre programme avec du HTML, du CSS, et du... JavaScript !

Souvenez-vous de la fin de la partie "La page HTML : le coeur de l'application", je vous parlais de mystérieuses classes permettant d'utiliser facilement les "fonctions" proposées nativement par AIR (la gestion des bases de données, le drag'n'drop, etc.). Eh bien nous allons commencer dès maintenant à les utiliser !

So, here we go ! Première étape, instancier la classe permettant l'utilisation des bases de données locales, j'ai nommé SQLConnection. Et comme je vous l'avais dit, nous allons utiliser le fameux alias "air." pour y accéder.
Code : JavaScript
1
var conn = new air.SQLConnection(); // On instancie la classe, et on la stocke dans la variable "conn" (pour connexion).


À ce stade du code, aucune connexion n'a été établie, pour la simple et bonne raison que le simple fait d'instancier la classe ne fait pas grand chose !
Instancier la classe ne suffit pas ? Mais comment on fait pour se connecter alors ?!

Minute papillon, tu n'as pas remarqué que pour le moment, tu n'as fourni aucune information quant à la base de données à laquelle tu voulais te connecter, ni même aucun identifiant de connexion ? :-°

En effet, et contrairement à PHP (eh oui, toujours l'exemple de PHP !), la connexion à la base de données ne nécessite aucun identifiant ! Les paramètres à faire passer à la fonction de connexion sont l'adresse vers le fichier de la base de données, et le mode de connexion à cette dernière.
Voyez plutôt :
Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var db_fichier = air.File.applicationStorageDirectory.resolvePath('ma_bdd.db'); //la variable "db_fichier" contient l'adresse vers le fichier de la base de données

try
{
	conn.open(db_fichier, air.SQLMode.CREATE); //on utilise la fonction "open" de la classe "SQLConnection" pour tenter de se connecter
	air.trace('Connexion reussie');
}
catch (error)
{
	air.trace('Erreur lors de la connexion : \n'+ error.message); //si erreur il y a, on affiche un message
	air.trace('Détails : \n'+ error.details);
}


Passons maintenant à une explication un peu plus complète du bout de code ci-dessus.

Après avoir défini le chemin vers le fichier de la BDD (base de données), on utilise la structure try...catch pour tenter la connexion.

Analyse du contenu du "try"



Dans le try, nous utilisons la méthode de connexion fournie par la classe SQLConnection. Cette méthode se voit affublée de deux paramètres : l'adresse du fichier de la BDD (précédemment défini dans la variable db_fichier), et le mode de connexion à la BDD (facultatif).

Il existe trois modes de connexion à une BDD :

Après avoir utilisé la méthode "open", et si la connexion a réussi, on inscrit dans la console un jôôli message au moyen de la fonction trace() (fonction très utile pour déboguer ;) ).
Si la connexion a échoué, on passe le relai au catch.

Analyse du contenu du catch



Nous irons dans cette partie plus vite que pour le try, puisque nous n'avons qu'une chose à étudier : l'objet mis à disposition par le catch.
Ce dernier, accessible par la variable error dans cet exemple, nous permet d'avoir plus de précisions sur l'erreur qui s'est produite, et qui a empêché la connexion à la BDD.

Pour accéder à ses informations, il suffit d'utiliser les propriétés de l'objet contenu dans error, qui n'est autre qu'une instance de la classe SQLError.
Les principales informations (à notre niveau actuel) sont délivrées par error.message et error.details. Elles nous permettront, dans la majeure partie des cas, de localiser l'origine du problème.

Nous verrons d'autres de ces propriétés dans le prochain chapitre, et plus particulièrement dans la partie "Gestion des erreurs" de celui-ci.

Pour ceux qui aiment les solutions toutes prêtes, je mets à disposition le code en entier de la connexion à une BDD (bien qu'il suffise de coller les deux bouts de codes précédents...) :

Secret (cliquez pour afficher)
Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var conn = new air.SQLConnection(); // on instancie la class, et on la stocke dans la variable "conn" (pour connexion)
var db_fichier = air.File.applicationStorageDirectory.resolvePath('ma_bdd.db'); //la variable "db_fichier" contient l'adresse vers le fichier de la base de données

try
{
	conn.open(db_fichier, air.SQLMode.CREATE); //on utilise la fonction "open" de la class "SQLConnection" pour tenter de se connecter
	air.trace('Connexion reussie');
}
catch (error)
{
	air.trace('Erreur lors de la connexion : \n'+ error.message); //si erreur il y a, on affiche un message
	air.trace('Détails : \n'+ error.details);
}


Modifier une base de données



Toute modification d'une base de données avec AIR, que se soit par l'ajout, la suppression, ou la mise à jour de données ou de tables, est rendue un poil plus complexe à cause de l'utilisation des Statements.

De plus, il n'existe pas d'application à la PHPMyAdmin pour le moment (ce qui n'est pas un mal en soi...).

Conclusion : c'est maintenant qu'on commence à rigoler. :p

En effet, la classe SQLConnection seule ne nous permet pas d'exécuter de requêtes sur la table ! Comme je l'ai dit plus haut, AIR nous force à passer par une classe "relai" : la classe SQLStatement. Voyez plutôt :
Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// pour que ce code puisse fonctionner, le script doit déjà être connecté à une BDD =)
var sql = 
	"CREATE TABLE IF NOT EXISTS codes (" + 
	"    c_ID INTEGER PRIMARY KEY AUTOINCREMENT, " + 
	"    c_auteur VARCHAR, " + 
	"    c_type VARCHAR, " +
	"    c_date INTEGER, " +
	"    c_code TEXT" +
	")";
	
var createStmt = new air.SQLStatement();
createStmt.sqlConnection = conn; // conn est la variable dans laquelle est instanciée la classe SQLConnection

createStmt.text = sql;

try
{
	createStmt.execute();
}
catch (error)
{
	air.trace('Erreur : \n'+ error.message);
	air.trace('Détails : \n'+ error.details);
}


N'oublions pas qu'ici, le but de la manoeuvre est de créer une table dans la BDD à laquelle nous venons de nous connecter. Pour cela, on définit une variable sql qui contient le code SQL de la requête à exécuter (vous êtes supposés comprendre ce code, je ne reviens donc pas dessus ;) ).

Ensuite, nous instancions la classe SQLStatement à l'intérieur d'une variable (ici : createStmt) :
Code : JavaScript
1
var createStmt = new air.SQLStatement();

un statement (ou littéralement "déclaration") permet de définir le code SQL qui sera exécuté, les paramètres qui seront utilisés, et quelle connexion sera utilisée.

Toute requête SQL dont avoir son statement associé. Donc si vous faites x requêtes SQL, vous instancierez la classe SQLStatement x fois.

Une fois le statement créé, nous allons lui dire avec quelle BDD il va devoir travailler (car oui, il est possible de travailler avec plusieurs BDD simultanément, mais nous y reviendrons plus tard), et ça, c'est ce petit bout de code qui s'en charge :
Code : JavaScript
1
createStmt.sqlConnection = conn; // conn étant la variable dans laquelle est instanciée la classe SQLConnection

Enfin, avant d'exécuter la requête, nous allons transmettre au statement le code qu'il devra exécuter. Et le statement, qui ne l'oublions pas est un objet, possède une propriété dont c'est justement le rôle.
Code : JavaScript
1
createStmt.text = sql; //la propriété "text" du statement vaut désormais la même chose que la variable "sql"

Au stade où nous en sommes, tout est prêt pour l'exécution de la requête. Nous allons donc la lancer, et utiliser une structure try...catch pour pouvoir réagir en cas d'échec de la requête.
Code : JavaScript
1
2
3
4
5
6
7
8
9
try
{
	createStmt.execute();
}
catch (error)
{
	air.trace('Erreur : \n'+ error.message);
	air.trace('Détails : \n'+ error.details);
}

Comme vous pouvez le voir dans le try, la fonction execute() de la classe SQLStatement se charge d'exécuter la requête.

Pour ce qui est du contenu du catch, les explications sont les mêmes que dans la partie précédente, je ne reviens donc pas dessus.

Notre BDD étant maintenant pourvue d'une table, nous allons pouvoir y insérer des données, et travailler avec !

Conseil :: si la BDD de votre application doit contenir des données dès l'installation, ou même pour ne pas exécuter la/les requête(s) de création des tables à chaque lancement, vous pouvez tester l'existence du fichier de votre BDD (variable db_fichier dans mes exemples).
Si le fichier existe, on considère que les tables existent et qu'elles sont peuplées. Sinon, on les crée et les peuple.
Mais pour savoir comment effectuer cette vérification, vous devrez attendre d'avoir lu le chapitre "Travailler avec les fichiers". :p

Insérer, modifier, ou supprimer des données

Le code pour insérer/modifier/supprimer des données étant sensiblement le même, je n'expliciterai que celui permettant d'insérer des données dans la BDD, et me contenterai de donner des exemples (commentés) pour les autres.
De plus, vous verrez que le code est très proche de celui que nous venons de voir pour créer des tables. :)

Insérer des données



Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// pour que ce code puisse fonctionner, le script doit déjà être connecté à une BDD =)

var insertStmt = new air.SQLStatement(); //création du statement
insertStmt.sqlConnection = conn; // conn est la variable dans laquelle est instanciée la class SQLConnection

var sql = 
    'INSERT INTO codes (c_auteur, c_type, c_date, c_code) ' + 
    'VALUES (:auteur, :type, :date, :code)';//définition de la requête qui sera exécutée
insertStmt.text = sql;

// assignation des valeurs aux paramètres de la requêtes
insertStmt.parameters[':auteur'] = 'K-Phoen';
insertStmt.parameters[':type'] = 'Tuto';
insertStmt.parameters[':date'] = '1210435277';
insertStmt.parameters[':code'] = 'Bouh !';

insertStmt.text = sql;

try
{
	insertStmt.execute();
}
catch (error)
{
	air.trace('Erreur : \n'+ error.message);
	air.trace('Détails : \n'+ error.details);
}

Tout comme pour créer une table, on commence par créer le statement et par définir avec quelle BDD il devra travailler.
Vient ensuite le moment de définir la requête qu'il devra exécuter, on remarquera ici un petit ajout dans le code de la requête :
Code : JavaScript
1
2
3
var sql = 
    'INSERT INTO codes (c_auteur, c_type, c_date, c_code) ' + 
    'VALUES (:auteur, :type, :date, :code)';

Comme vous pouvez le voir, nous utilisons des paramètres dans notre requête. Ces derniers sont de la forme :mon_paramètre, et leurs valeurs seront définies plus bas dans le code, en renseignant la propriété parameters de la classe SQLStatement, comme vous pouvez le voir dans le code ci-dessous :
Code : JavaScript
1
2
3
4
insertStmt.parameters[':auteur'] = 'K-Phoen';
insertStmt.parameters[':type'] = 'Tuto';
insertStmt.parameters[':date'] = '1210435277';
insertStmt.parameters[':code'] = 'Bouh !';

Il y a plusieurs avantages à utiliser des paramètres :

Pour le reste du code, il est semblable à celui utilisé pour créer une table, je suppose donc que vous arrivez maintenant à le comprendre.

Modifier des données



Vous l'aurez compris, il suffira ici de modifier le nom de la variable contenant le statement ainsi que le code de la requête pour parvenir à nos fins. Je me contenterai donc de vous donner un exemple de requête.

Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// pour que ce code puisse fonctionner, le script doit déjà être connecté à une BDD

var updateStmt = new air.SQLStatement(); //création du statement
updateStmt.sqlConnection = conn; // conn est la variable dans laquelle est instanciée la classe SQLConnection

var sql = 
    'UPDATE codes SET c_auteur = :auteur, c_code = :code ' + 
    'WHERE c_ID = :ID'; //définition de la requête qui sera exécutée
updateStmt.text = sql;

// assignation des valeurs aux paramètres de la requêtes
updateStmt.parameters[':ID'] = 3;
updateStmt.parameters[':auteur'] = 'K-Phoen';
updateStmt.parameters[':code'] = 'Re-bouh !';

updateStmt.text = sql;

try
{
	updateStmt.execute();
}
catch (error)
{
	air.trace('Erreur : \n'+ error.message);
	air.trace('Détails : \n'+ error.details);
}


Supprimer des données



Pour ce qui est de la suppression de données, et là je vais vous surprendre, c'est exactement la même chose !

Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
var deleteStmt = new air.SQLStatement(); //création du statement
deleteStmt.sqlConnection = conn; // conn est la variable dans laquelle est instanciée la classe SQLConnection

var sql = 'DELETE FROM codes WHERE c_ID = :ID'; //définition de la requête qui sera exécutée
deleteStmt.text = sql;

// assignation des valeurs aux paramètres de la requêtes
deleteStmt.parameters[':ID'] = 3;

deleteStmt.text = sql;

try
{
	deleteStmt.execute();
}
catch (error)
{
	air.trace('Erreur : \n'+ error.message);
	air.trace('Détails : \n'+ error.details);
}


Maintenant que vous savez comment peupler votre BDD, nous allons voir comment récupérer et utiliser son contenu. :)

Récupérer des données

Imaginons rien qu'un instant que vous avez une BDD peuplée avec les noms, prénoms, et numéros de carte bancaire de pas mal de personnes (on peut toujours rêver :soleil: ). Ne serait-il pas rageant de ne pas pouvoir récupérer toutes ces infos ?

Parce que je suis super gentil, et parce que vous partagerez certainement avec moi les richesses acquises grâce à ce tuto, je vais vous expliquer comment récupérer vos données.

Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var selectStmt = new air.SQLStatement(); //création du statement
selectStmt.sqlConnection = conn; // conn est la variable dans laquelle est instanciée la classe SQLConnection

var sql = 'SELECT c_ID, c_nom, c_prenom, c_numero FROM codes_bancaires WHERE c_prenom = :prenom'; //définition de la requête qui sera exécutée
selectStmt.text = sql;

// assignation des valeurs aux paramètres de la requêtes
selectStmt.parameters[':prenom'] = 'K-Phoen';

try
{
	selectStmt.execute();
	var result = selectStmt.getResult(); //result contient les résultats de la requête
	var numRows = result.data.length; //contient le nombre de résultats retournés

	for (var i = 0; i < numRows; i++) //on bloucle les résultats
	{
		var row = result.data[i];
		air.trace('ID :: '+row.c_ID+'; Nom :: '+row.c_nom+'; Code :: '+row.c_numero+'; etc ...');
	}
}
catch (error)
{
	if( error.message != 'Null value' ) // si aucune enregistrement n'est retourné
	{
		air.trace('Erreur : \n'+ error.message);
		air.trace('Détails : \n'+ error.details);
	}
	else
	{
		air.trace('Aucun enregistrement retourné !');
	}
}

Étant donné que vous êtes désormais super calés dans l'exécution de requêtes SQL sous AIR, et que les statements n'ont plus aucun secret pour vous, je me contenterai d'expliciter le contenu du try et du catch.

Analyse du try



Donc c'est parti, la requête a été faite et envoyée (grâce à la méthode exécute de la classe SQLStatement), il ne nous reste plus qu'à traiter les résultats. Mais avant de les traiter, faudrait peut-être bien penser à les récupérer, et à les stocker (dans une variable par exemple). Et ça, c'est cette ligne qui s'en charge :
Code : JavaScript
1
var result = selectStmt.getResult();

Ici, on utilise la méthode getResult, pour stocker le résultat de la requête dans la variable result.

Ensuite, on va faire une boucle pour traiter chaque résultat renvoyé. Pour cela, on utilise la structure for( ...; ...; ... ), structure qui nécessite de connaître le nombre de résultats retournés. Coup de chance pour nous, l'exemple que j'ai fourni nous montre comment avoir ce genre d'information. Voyez plutôt :
Code : JavaScript
1
var numRows = result.data.length;

Si aucun enregistrement n'est retourné, ce n'est pas le contenu du try qui sera exécuté, mais celui du catch !

Nous partons du principe qu'au moins un enregistrement a été retourné. Nous nous situons donc dans le try, et nous allons commencer une boucle pour traiter les résultats.

De manière à rendre le code plus lisible, on définit une variable row qui contiendra les données relatives à l'enregistrement en cours de traitement :
Code : JavaScript
1
var row = result.data[i];

Et le contenu de cette variable n'est pas, comme on pourrait s'y attendre, un array mais un objet ! Les propriétés de ce dernier étant évidemment les colonnes de notre table.
Sachant cela, il n'y a rien de plus simple qu'accéder à ces données, la preuve :
Code : JavaScript
1
air.trace('ID :: '+row.c_ID+'; Nom :: '+row.c_nom+'; Code :: '+row.c_numero+'; etc ...');


Analyse du catch



Comme je vous l'ai dit plus haut, il y a deux cas de figure pour lesquels nous entrerons dans le catch :

Pour déterminer dans quel cas nous nous trouvons, il suffit de tester le contenu de la propriété message. En effet, si aucun enregistrement n'est retourné, cette propriété aura pour valeur Null value, nous saurons donc qu'aucune donnée n'est à traiter.
Si la valeur de message est différente, c'est qu'il y a eu une erreur, et nous agirons en conséquence... :pirate:

Ce qu'il faut retenir

L'utilisation d'une BDD sous AIR requiert l'instanciation de deux classes (la majeure partie du temps) : SQLConnection et SQLStatement.

La connexion à une BDD est permise par la méthode open de la classe SQLConnection. Elle admet deux paramètres : l'adresse du fichier de la BDD, et le mode de connexion (voir la partie "Se connecter à une base de données, et la modifier" pour plus de précisions).
Code : JavaScript
1
2
3
var db_fichier = air.File.applicationStorageDirectory.resolvePath('ma_bdd.db'); //la variable "db_fichier" contient l'adresse vers le fichier de la base de données

conn.open(db_fichier, air.SQLMode.CREATE); // le second paramètre indique le mode de connexion


Pour toute modification d'une BDD, au niveau des tables aussi bien que des données, le code ressemblera fortement à celui-ci :
Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// pour que ce code puisse fonctionner, le script doit déjà être connecté à une BDD =)

var queryStmt = new air.SQLStatement(); //création du statement
queryStmt.sqlConnection = conn; // conn est la variable dans laquelle est instanciée la classe SQLConnection

var sql = 
    'INSERT INTO codes (foo) ' + 
    'VALUES (:bar)';v//définition de la requête qui sera exécutée
queryStmt.text = sql;

// assignation des valeurs aux paramètres de la requêtes
queryStmt.parameters[':bar'] = 'K-Phoen';

queryStmt.text = sql;

try
{
	queryStmt.execute();
}
catch (error)
{
	air.trace('Erreur : \n'+ error.message);
	air.trace('Détails : \n'+ error.details);
}

Cependant, le contenu du try...catch change légèrement pour une requête de type SELECT (la construction et l'exécution de la requête ne diffère pas, mais on ajoute une partie "récupération et traitement des données") :
Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
try
{
	selectStmt.execute();
	var result = selectStmt.getResult(); //result contient les résultats de la requête
	var numRows = result.data.length; //contient le nombre de résultats retournés

	for (var i = 0; i < numResults; i++) //on bloucle les résultats
	{
		var row = result.data[i];
		air.trace('ID :: '+row.c_ID+'; Nom :: '+row.c_nom+'; Code :: '+row.c_numero+'; etc ...');//où c_ID, c_nom et c_numero sont les noms des colonnes de la table
	}
}
catch (error)
{
	if( error.message != 'Null value' ) // si aucune enregistrement n'est retourné
	{
		air.trace('Erreur : \n'+ error.message);
		air.trace('Détails : \n'+ error.details);
	}
	else
	{
		air.trace('Aucun enregistrement retourné !');
	}
}

Si aucun enregistrement n'est retourné, ce n'est pas le contenu du try qui sera exécuté, mais celui du catch !

Toute requête SQL dont avoir son statement associé. Donc si vous faites x requêtes SQL, vous instancierez la classe SQLStatement x fois.

Bien que vous soyez désormais prêts à utiliser une base de données locale dans vos applications, ne zappez pas la partie deux sur les BDD, il y a de nouvelles notions, et pas des moindres ! ;)
Chapitre précédent Sommaire Chapitre suivant
Retour en haut Retour en haut


Créé : le 18/06/2008 à 15:42:54
Modifié : le 22/08/2008 à 15:50:52
Avancement : 100%
Licence : Copie non autorisée

1 commentaire

Changer de design | En savoir plus | Plan du site | Politique d'accessibilité | Règles | RSS tutoriels | RSS news
Édité par Simple IT SARL : Nous contacter | Notre blog | Revue de presse | Publicité

Y'a plus rien à lire, faut remonter maintenant !

Hébergement web - Correction de tutoriels - Créer un site
Vous souhaitez apparaître ici ? Contactez-nous.

Nombre de connectés 141 Zéros connectés | Requêtes SQL 8 requêtes | Temps de génération de la page : Total (SQL) 0.0402s (0.0285s)