• Billet écrit dans : Flex Flash Floush 02.02.2009

    Un peu d’SQL ça fait pas de mal non ?

    Je fais que peu de back admin en ce moment … j’écrit quasi pas de requêtes .. vive les ORM (object-relational mapping) .. et j’occupe mon temps libre à Flex/Flash et mon application de suivi de stats sportives.

    Je suis en train d’écrire une nouvelle version de mon application, avec un code plus propre, et surtout multi utilisateur afin que chacun inscrive ses statistiques sportives dans la même application. Je pourrais m’en sortir en utilisant à mort les HTTPService, faire un webservice et site dédié à la cause.. mais bon je n’ai pas vocation (pour l’instant) de créer un site pour se montrer le nombril … et imaginer le nombre de requêtes à traiter …

    En sachant que Air embarque nativement un moteur SQLite, pourquoi ne pas garder sur le poste du client toutes ses stats ? Quitte à faire par la suite un bouton « synchroniser sur le web » :) Ca peut le faire non ?

    I ) Easy mode

    Voyons voir, tapons « air sqlite » dans google et regardons un peu l’existant

    On se rend compte que le principe est assez simple au final :

    1. Je crée un fichier from scratch via la classe File
    2. Je l’ouvre à travers une SQLConnection
    3. Je crée un SQLStatement à partir de mon objet SQLConnection
    4. J’exécute ma requête pour obtenir un SQLResult et j’en extrait les données sous forme de tableau
    5. Simple non ?

    Mais bon, même si c’est l’affaire d’une quinzaine de ligne, c’est quand même un peu relou de tout faut tout se retapper à chaque requete .. autant avoir une classe bien sympa qui gère la BDD dans son coin non ?

    II ) Moi, j’ai la classe

    J’aime découper mes applications en MVC quand je le peux. Une classe qui gère ma BDD et qui centralise les appels, c’est cool. On appelle ça le « Model » :) Voici, sans prétention, ma chtite classe qui va bien :

    ?View Code ACTIONSCRIPT
    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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    
    package bdd
    {
    	import flash.data.SQLConnection;
    	import flash.data.SQLResult;
    	import flash.data.SQLStatement;
    	import flash.filesystem.File;
     
    	public class MySqlLite extends SQLConnection
    	{
    		protected var fichier:File;
     
    		// Pattern Singleton c'est mieux.
    		private static var instance:MySqlLite
     
    		public function MySqlLite(access:Singleton)
    		{
    			super();
     
    			// Initilisation de la base. Création des tables si besoin est.
    			init();
    		}
     
    		// Implémentation du singleton.
    		public static function getInstance():MySqlLite{
    			if(instance == null){
    				instance = new MySqlLite(new Singleton());
    			}
    			return instance;
    		}		
     
    		public function init():void
    		{
    			// Autant se créer notre fichier BDD dans le répertoire d'installation de notre Application non ?
    			fichier = new File(File.applicationDirectory.nativePath + "/Sports2009-bdd.bd")
     
    			// Si le fichier n'existe pas déjà, on crée nos tables !
    			if(!fichier.exists)
    			{
    				this.open(fichier);
    				var stmt:SQLStatement = new SQLStatement();
    				stmt.sqlConnection = this;
    				stmt.text = "CREATE TABLE performances (id INTEGER PRIMARY KEY AUTOINCREMENT, creation_date DateTime, calorie decimal, kilometre decimal, temps decimal)";
    				// Hop insertion de notre 1er table
    				stmt.execute();	
     
    				// Notre Statement est chaud bouillant pour créer une deuxième table, soyons fou.
    				stmt.text = "CREATE TABLE utilisateur (id INTEGER PRIMARY KEY AUTOINCREMENT, nom longvarchar, password longvarchar)";
    				stmt.execute();
    			}
    			else
    			{
    				// Le fichier existe, on ouvre notre bdd :)
    				this.open(fichier);
    			}
    		}
     
    		// On peut explicitement fermer la bdd ..
    		public function fermer():void
    		{
    			this.close();
    		}
     
    		// Exécutons notre requete SQL et retournons le résultat :)
    		public function requete(maRequeteSql:String):SQLResult
    		{
    			var requete:SQLStatement = new SQLStatement();
    			requete.sqlConnection =this;
    			requete.text = maRequeteSql
    			requete.execute();
     
    			// On récupère le résultat de l'execution
    			var r:SQLResult = new SQLResult()		
     
    			// ATTENTION on ne peut faire qu'un seul getResult()
    			// Pourquoi ? car c'est à usage unique
    			// une fois que l'on a demandé des infos "pssshhtt ça disparait !"
    			r =  requete.getResult();
    			return r;
    		}
     
    	}
    }
     
    class Singleton{
    	public function Singleton()
    	{
     
    	}
    }

    Utilisation

    Pour la gestion de mes utilisateurs par exemple, voici ma classe « Utilisateur » (Waahou je suis original) qui me sert à l’insertion et la connexion, etc d’un de mes gugus. Elle est vraiment basique, mais ça marche ;)

    On reste encore dans le « Model » :)

    ?View Code ACTIONSCRIPT
    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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    
    package users
    {
    	import bdd.MySqlLite;
    	import flash.data.SQLResult;
    	import flash.data.SQLStatement;
     
    	public class Utilisateur extends Object
    	{
     
    		private var name:String;
    		private var password:String;
     
    		public function Utilisateur(nom:String,pass:String)
    		{
    			super();
    			this.setName(nom);
    			this.setPassword(pass);
    		}
     
    		public function getName():String
    		{
    			return this.name;
    		}
     
    		public function getPassword():String
    		{
    			return this.password;
    		}
     
    		public function setName(nom:String):void
    		{
    			this.name= nom;
    		}
     
    		public function setPassword(pass:String):void
    		{
    			this.password = pass;
    		}
     
    		// Test voir si le gugus existe
    		public function existe():Boolean
    		{
    			var test:SQLResult = new SQLResult();
    			test = MySqlLite.getInstance().requete("SELECT * from utilisateur WHERE nom='" + this.name +"' and password='" + this.password +"' ");
    			return test.data != null
    		}
     
    		// Inscription du gugus
    		public function inscription():Boolean
    		{
    			if(!existe())
    			{
    				var test:SQLResult = new SQLResult();
    				test = MySqlLite.getInstance().requete("INSERT INTO utilisateur (nom,password) VALUES ('" + this.name +"','" + this.password +"') ");
    				return true;
    			}
    			else
    			{
    				return false;
    			}
    		}
     
    	}
    }

    Et le petit contrôleur qui va bien, extrait de mon code :

    ?View Code ACTIONSCRIPT
    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
    
    public function TestConnexion(e:ConnexionEvent):void
    {
    	var user:Utilisateur = new Utilisateur(e.sLogin,e.sPassword)
    	if(user.existe())
    	{
    		pannelConnexion.currentState = "OK"
    		this.currentState = "Dashboard";
    	}
    	else
    	{
    		pannelConnexion.currentState = "Erreur"
    	}
    }
     
    public function Inscription(e:ConnexionEvent):void
    {
    	var user:Utilisateur = new Utilisateur(e.sLogin,e.sPassword)
    	if(user.inscription())
    	{
    		trace("je me suis bien inscrit");
    	}
    	else
    	{
    		trace("j'existe déjà ...");
    	}
    }

    Vous notez que j’ai un évènement personnalisé qui contient le login & le password à tester. Voici son code pour ceux que ça intéresse, y a rien de spécial, c’est tout basique :

    ?View Code ACTIONSCRIPT
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    package Event
    {
    	import flash.events.Event;
     
    	public class ConnexionEvent extends Event
    	{
    		public var sLogin:String;
    		public var sPassword:String;
     
    		public function ConnexionEvent(type:String,login:String,password:String, bubbles:Boolean=false, cancelable:Boolean=false)
    		{
    			super(type, bubbles, cancelable);
    			sLogin = login;
    			sPassword = password;
    		}
     
    	}
    }

    Voilà, vous avez là un exemple très simpliste d’utilisation de SQLite dans Air. Pour tout dire, je ne suis pas encore aller très loin avec :)

    A vous de jouer !

    Billet écrit dans : Flex Flash Floush 02.02.2009

    Tags: , , ,

  • 6 Réactions !!

    WP_Modern_Notepad
    • Palleas dit:

      J’ai pas encore tout lu, mais il n’est pas un peu useless ton « extends Object » ?

    • Guillaume chave dit:

      Yep bien vu l’aveugle ^^

      J’ai créer ma classe avec Flex builder, et naturellement, sortant d’une période Java, j’ai extends Object en automatique :)

      Il est vrai que toute classe est par défaut un extends Object, mais bon si un jour ils sortent un autre object native genre « PapaObject » je suis sur que je pointerai sur le bon « Object » (bon oki, je me cherche des excuses un peu tiré par les cheveux ^^)

    • vorpal dit:

      pourrais tu me fournir tes sources, je suis débutant en flex et j ai ces erreurs :
      1120: Accès à la propriété non définie MySqlLite. Guillaume chave/src/users Utilisateur.as line 38
      1120: Accès à la propriété non définie MySqlLite. Guillaume chave/src/users Utilisateur.as line 47

    • Guillaume chave dit:

      Peut être as tu des imports mal réglé ? C’est un problème Flash ça pas Flex :)
      Je suis désolé mais ce code étant un extrait d’un projet plus conséquent mes sources ne t’aiderait pas, loin de là.
      Comme disais un de mes prof, autant te donner une bouée en béton.

      Au pire tu m’envoies ton projet et j’essaie de corriger :)

    • vorpal dit:

      Effectivement c était un probléme de chemin d import.

      J’aurais une autre question :
      pourquoi un singleton pour la connexion a SQLite ? Pour qu’il n’y ait qu’une seule requête passée à la fois?

    • Guillaume chave dit:

      Pour le singleton, c’est pas vraiment liée aux requêtes (même si ça peut le faire pour le comportement que tu cites) mais liée au fichier de stockage.
      Il faut l’ouvrir pour exécuter des requêtes dedans, image le ouvert plusieurs fois en même temps pour faire des insert/delete .. ça planterait lamentablement.

      Puis le singleton est plus cool à utiliser ^^ t’a qu’une instance de ta base de donnée qui est accessible partout dans ton code, une instance qui centralise tout. Moi j’aime :)

    Réagissez a cet article ?!

    Attention: Les commentaires sont modérés et ne sont pas visibles automatiquement. Ce n'est pas la peine de re-soumettre votre commentaire.

CV Guillaume chave