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)
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

).
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 : JavaScript1 | 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 :
- air.SQLMode.CREATE : si la BDD existe elle sera ouverte, sinon elle sera créée (si le mode n'est pas défini lors de l'appel de la méthode "open", le mode CREATE sera utilisé) ;
- air.SQLMode.READ : ouvre une BDD en mode "lecture seule" ;
- air.SQLMode.UPDATE : si la BDD existe elle sera ouverte, mais la BDD n'est pas créée si elle n'existe pas.
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.
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 : JavaScript1 | 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 : JavaScript1 | 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 : JavaScript1 | 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 : JavaScript1
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 !
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 : JavaScript1
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 : JavaScript1
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 :
- de meilleures performances avec les paramètres plutôt qu'avec une concaténation des variables ;
- plus de sécurité ;
- une lisibilité du code accrue (enfin ça, c'est mon avis
).
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.
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

). 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 : JavaScript1 | 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 : JavaScript1 | 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 : JavaScript1 | 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 : JavaScript1 | 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 :
- si aucun enregistrement n'a été retourné ;
- si une erreur a eu lieu.
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...
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 : JavaScript1
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.