¿Quieres registrarte?

Air - Clase en ActionScript 3 para manejar bases SQLite.

Por: phoxer
25 de Marzo del 2009
696 de clabLevel
Otros artículos de phoxer
2,760 visitas

Hola como estan??

Voy compartir una clase que desarrollé que podría ser muy útil para todos los que trabajan con Air y SQLite (base local) o quieran hacerlo, ya que entre todos tenemos que hacer a esta maravillosa aplicación conocida y destruir a hacerle competencia a Silverlight jaja (bromilla).. (o no.. :roll: )

He estado rompiéndome la cabeza un poco para pasar los métodos que tengo de conexión de PHP a ActionScript 3, para poder manejar registros simples, como UPDATE, INSERT y SELECT desde una sola clase y lo he conseguido!!.

Voy a tratar de ser breve..
Desde ActionScript 3 la implementación es muuuuy simple.. en este caso trabajo desde Flex 3, vamos por pasos.

Primero, importamos la clase y hacemos la conexión, la clase automáticamente creará la base de datos si no existe:

Código :

import phoxer.DataManager.AirSqlManager;
 
private var database:AirSqlManager;
private function onComplete():void{
   database = new AirSqlManager("test.db");
}


Segundo, creamos las tablas:

Código :

//CREAR LA TABLA
var campos:Object= new Object();
campos.id="INTEGER PRIMARY KEY  NOT NULL";
campos.titulo="TEXT";
campos.fecha="TEXT";
 
var tableTareasToCreate:Object= new Object();
tableTareasToCreate.tabla="tareas";
tableTareasToCreate.campos=campos;
database.createTable(tableTareasToCreate,insertTarea);


El metodo createTable(); utiliza 3 parametros.

Terminaria devolviendo un query asi:
CREATE TABLE IF NOT EXISTS tareas (`titulo` TEXT,`id` INTEGER PRIMARY KEY NOT NULL,`fecha` TEXT)

Tercero, Incertando un registro

Código :

//INSERTAR REGISTRO
var campos:Object= new Object();
campos.titulo="Registro 1";
campos.fecha="20/08/2009";
 
var dataToInsert:Object = new Object();
dataToInsert.tabla="tareas";
dataToInsert.datos=campos;
database.setInsert(dataToInsert,consultar);


El metodo setInsert(); utiliza 3 parametros.

Terminaria devolviendo un query asi:
INSERT INTO tareas (titulo,fecha) VALUES ('Registro 1','20/08/2009')

Cuarto, haciendo una consulta

Código :

//HACER UNA CONSULTA
var tableToConsult:Object= new Object();
tableToConsult.tabla="tareas";
tableToConsult.principal="id";
tableToConsult.orden="DESC";
database.setSelect(tableToConsult,leerDatos,onError);

private function leerDatos(dts:Array):void{
   for each(var dt:Object in dts){
      trace(dt.id+" "+dt.titulo+" "+dt.fecha);
   }
}

private function onError():void{
   trace("no se pudo hacer la consulta");
}


El método setSelect(); utiliza 3 parámetros.

Terminaria devolviendo un query asi:
SELECT * FROM tareas ORDER BY id DESC

Para hacer una consulta mas rigurosa:

Código :

//HACER UNA CONSULTA
var tableToConsult:Object= new Object();
tableToConsult.tabla="tareas";
tableToConsult.principal="id";
tableToConsult.orden="DESC";
tableToConsult.filtro="titulo";
tableToConsult.same="Registro";
database.setSelect(tableToConsult,leerDatos,onError);

private function leerDatos(dts:Array):void{
   for each(var dt:Object in dts){
      trace(dt.id+" "+dt.titulo+" "+dt.fecha);
   }
}
private function onError():void{
   trace("no se pudo hacer la consulta");
}

Si ven se agregaron dos opciones mas "filtro y same", esto nos va a devolver los registros cuando ejemplo: "titulo" sea igual a "Registro".
Terminaría devolviendo un query asi:
SELECT * FROM tareas WHERE titulo ='Registro' ORDER BY id DESC

Quinto, haciendo una modificación:

Código :

//MODIFICAR UN REGISTRO
var datos:Object=new Object();
datos.titulo="Modificado";
datos.fecha="1/09/2009";
 
var registroAModificar:Object = new Object();
registroAModificar.tabla="tareas";
registroAModificar.datos=datos;
registroAModificar.campo="id";
registroAModificar.valor="3";
database.setUpdate(registroAModificar);


el metodo setUpdate(); utiliza 3 parametros.

Terminaria devolviendo un query asi:
UPDATE `tareas` SET `titulo`='Modificado',`fecha`='1/09/2009' WHERE id='3'

Bien como vemos con esta clase se nos resulta muyyy facil conectarnos a una base de datos SQLite y manejarla, que les parece??..
Me faltan mas métodos y a medida que voy mejorándola la voy subiendo aca y en http://www.phoxer.com/es/blog/post_41/ :)

haaa me olvidaba, acá esta la la clase AirSqlManager:

Código :

/**
Air SQLite Manager
By ::[PHOXER]::
http://www.phoxer.com
v 1.1;
*/
package phoxer.DataManager{
   import flash.data.SQLConnection;
   import flash.data.SQLResult;
   import flash.data.SQLStatement;
   import flash.errors.SQLError;
   import flash.events.SQLErrorEvent;
   import flash.events.SQLEvent;
   import flash.filesystem.File;
 
   public class AirSqlManager{
      private var conexion:SQLConnection;
        private var BDFile:File;
        private var State:SQLStatement = new SQLStatement();
   public function AirSqlManager(db:String,asy:Boolean=false){
      conexion = new SQLConnection();
      conexion.addEventListener(SQLEvent.OPEN,onDbOpen,false,0,true);
      conexion.addEventListener(SQLErrorEvent.ERROR,onDbError,false,0,true);
      BDFile=File.applicationStorageDirectory.resolvePath(db);
      trace("DB PATH: "+BDFile.nativePath)//path actual.
      trace("DB EXIST: "+BDFile.exists)//si existe la base.
      if(asy){
         conexion.openAsync(BDFile);
      }else{
         conexion.open(BDFile);
      }
   }
   private function onDbOpen(e:SQLEvent):void{
      trace("DB CONECTED")
      State.sqlConnection = conexion;
   }
   private function onDbError(e:SQLErrorEvent):void{
      trace("DB Error: SqlData: "+e)
   }
 
   public function createTable(Obj:Object,bk:Function=null,err:Function=null):void{
      var campos:Object=Obj.campos;
      var sql:String="CREATE TABLE IF NOT EXISTS "+Obj.tabla+" (";
      var cmp:String="";
      for(var dt:Object in campos){
         cmp+="`"+dt+"` "+campos[dt]+",";
      }
 
      cmp=cmp.substring(0,cmp.length-1);
      sql+=cmp+")";
      trace(sql);
      State.text=sql;
      try{
         State.execute();
         if(bk!=null){
            bk();
         }
      }catch (e:SQLError){
         trace("CREATE ERROR: "+e);
         if(err!=null){
            err();
         }
      }
 
   }
 
   public function setSelect(Obj:Object,bk:Function=null,err:Function=null):void{
      var tabla:String=Obj.tabla;
      var principal:String=Obj.principal;
      var orden:String=Obj.orden;
      var filtro:String=Obj.filtro;
      var same:String=Obj.same;
      var like:String=Obj.like;
      var limite:String=Obj.limit;
      var select:String=Obj.select;
      //-limit
      limite=(limite!="" && limite!=null)? String(" LIMIT "+limite):"";
      //-Select
      select=(select!="" && select!=null)? String("`"+select+"`"):"*";
      //-SQL
      var sql:String;
      if(filtro!="" && filtro!=null && same!="" && same!=null) {
            sql="SELECT "+select+" FROM "+tabla+" WHERE "+filtro+" ='"+same+"' ORDER BY "+principal+" "+orden+" "+limite;
      }else if(filtro!="" && filtro!=null && like!="" && like!=null){
            sql="SELECT "+select+" FROM "+tabla+" WHERE "+filtro+" LIKE '%"+like+"%' ORDER BY "+principal+" "+orden+" "+limite;
      }else{
            sql="SELECT "+select+" FROM "+tabla+" ORDER BY "+principal+" "+orden+" "+limite;
      }
      trace(sql);
      State.text=sql;
      try{
         State.execute();
         //var result:SQLResult=State.getResult();
         if(bk!=null){
            var result:SQLResult = State.getResult();
            bk(result.data);
         }
      }catch (e:SQLError){
         trace("SELECT ERROR: "+e);
         if(err!=null){
            err();
         }
      }
   }
 
   public function setInsert(Obj:Object,bk:Function=null,err:Function=null):void{
      var datos:Object=Obj.datos;
      var sql:String="INSERT INTO "+Obj.tabla+" (";
      var campos:String="";
      var valores:String="";
      for(var dt:Object in datos){
         campos+=dt+",";
         valores+="'"+String(datos[dt])+"',";
      }
      campos=campos.substring(0,campos.length-1);
      valores=valores.substring(0,valores.length-1);
      sql+=campos+") VALUES ("+valores+")";
      trace(sql);
      State.text=sql;
      try{
         State.execute();
         //var result:SQLResult=State.getResult();
         if(bk!=null){
            bk();
         }
      }catch (e:SQLError){
         trace("INSERT ERROR: "+e);
         if(err!=null){
            err();
         }
      }
   }
 
   public function setUpdate(Obj:Object,bk:Function=null,err:Function=null):void{
      var tabla:String=Obj.tabla;
      var datos:Object=Obj.datos;
      var campo:String=Obj.campo;
      var valor:String=Obj.valor;
      var sql:String="UPDATE `"+tabla+"` SET "
      var sets:String="";
      for (var dt:Object in datos){
         sets+= "`"+dt+"`='"+String(datos[dt])+"',";
      }
      sets=sets.substring(0,sets.length-1);
      sql+=sets+" WHERE "+campo+"='"+valor+"'";
 
      trace(sql);
      State.text=sql;
      try{
         State.execute();
         //var result:SQLResult=State.getResult();
         if(bk!=null){
            bk();
         }
      }catch (e:SQLError){
         trace("INSERT ERROR: "+e);
         if(err!=null){
            err();
         }
      }
   }
}


Espero que entre todos la mejoremos aportando ideas..
Saludos, phoxer.

Enviar a twitter Enviar a facebook


También te interesa


Etiquetas air actionscript_3

Comentarios | Enviar un comentario
Exelente!!! Muy buena tu clase. Seguro la utilizare en mis proyectos.
Por: AXM
esta bien, un poco de POO no caería mal
Por: eldervaz
@eldeveraz, si se que estan programadas a lo bestia jeje, estaría bueno que entre todos optimicemos las funciones de manejo simple :)

por ejemplo este tipo de trato
sets=sets.substring(0,sets.length-1);
(quitarle la ultima coma)
se podría evitar quizas con otra técnica, aunque no se si con RegExp sera mejor?

Saludos.
Por: phoxer
Gracias por compartir la clase (y)
intentaremos optimizarla para hacerla más manejable ;)
Por: Zguillez
Phoxer muy buena! no creo que convenga hacer una regexp para tan sólo quitar una coma, conviene usarlas para operaciones más comlpejas.

sets=sets.substring(0,sets.length-1);
No es lo mismo que esto:
sets=sets.substr(0,-1);

Bueno nuevamente muy bueno!
Por: Raxiro-blog
Gracias Zguillez, yo creo que de apoco y entre todos la podemos mejorar.

@Raxiro gracias por tu aporte, si creo que ese método es mejor, ya modifique la clase, esta en la versión 1.2
Por: phoxer
Por favor! no es un aporte lo mio :$, a lo sumo será un 0,000001% de lo que hiciste :P o menos!
Por: Raxiro-blog

Raxiro-blog :

Por favor! no es un aporte lo mio :$, a lo sumo será un 0,000001% de lo que hiciste :P o menos!

Cualquier aporte con buenas intenciones e incluso para mejorar el rendimiento, como es en tu caso, es valido.. :)
Gracias.
Por: phoxer
muy buen aporte
gracias
Por: andres felipe-blog
excelente aporte....muchas gracias por compartirlo
Por: bubudrc
Gracias por compartirla, con esto puedo empezar a trabajar con SQLite.

Te haré llegar algunas modificaciones ;)
Por: GersonM_17
Reconozco que, igual que tiene buena pinta, no me gusta demasiado el modo de usar los argumentos. Personalmente (pero ya te digo que es sólo una opinión) haría que fueran muy parecidas a las instrucciones SQL, devolviendo valores, en lugar de estar "arriba y abajo" con las funciones. P.e.

Código :


public int function AirSqlManager(db:String,asy:Boolean=false)

//devuelve 1 si se ha creado ó 0 si no se ha creado


Por otra parte me haría una Clase "Tabla", de modo que createTable sería más o menos

Código :


public Tabla function createTable(tabla:String,Obj:Object)


Devolviendo null caso de que no se haya podido crear la tabla.

A la hora de insertar/seleccionar/updatar usaríamos los objetos tabla y, de nuevo, devolvería argumentos. P.e.

Código :


//es un "método" de la clase Tabla.

public int function setInsert(Obj:Object)

//devuelve 1 si se ha insertado o 0 si no se ha insertado


Claro que cambia todo un poco, pero un programa podría ser más o menos

Código :


  database:AirSqlManager = new AirSqlManager("test.db"); 

var campos:Object= new Object(); 

campos.id="INTEGER PRIMARY KEY  NOT NULL"; 

campos.titulo="TEXT"; 

campos.fecha="TEXT"; 

titulos:Tabla=AirSqlManager.createTable("tareas",campos)



campos:Object= new Object(); 

campos.titulo="Registro 1"; 

campos.fecha="20/08/2009"; 

titulos.Insert(campos)


Por: Eliseo-blog
Hola Eliseo, Tiene buena pinta y voy a probarlo como dices, la clase la hice asi porque es como estoy acostumbrado jaja, pero obvio que estoy abierto a métodos y técnicas mejores..

Me gusta también tu forma de manejar los retornos asi que voy a probarlo, lo que no entendí bien es cuando dices

Eliseo-blog :


Por otra parte me haría una Clase "Tabla", de modo que createTable sería más o menos

Código :

public Tabla function createTable(tabla:String,Obj:Object)

Devolviendo null caso de que no se haya podido crear la tabla.


como es eso, seria una clase aparte por cada metodo SQL? .

Quisiera saber para aprender también cual es la diferencia entre pasar una funcion de retorno a que el mismo método devuelva el resultado.

Saludos.
Por: phoxer
NO, no es una Clase por cada método SQL.

Repensemos un poco el problema.

Tenemos dos Clases distintas:
1.-AirSqlManager
2.-Tabla
La Clase AirSqlManager debería tener un array con las tablas y dos métodos
1.-createTable
2.-setSelect //<--para consultas que impliquen más de una tabla

La Clase Tabla tendría como variables
1.-la base de datos a la que pertenece
2.-El nombre de la tabla

y los métodos
1.-setUpdate
2.-setSelect
3.-setInsert
4.-setDelete

Los métodos quedan muy parecidos a los que teníamos anteriormente, aunque lógicamente no tenemos que pasarles el "argumento" con el nombre de la tabla.

Y no existe demasiada diferencia entre pasar una función de retorno a que se devuelva un resultado. Pero para mí -es opinión personal- queda más claro algo como

Código :


var estructura:Object=new Object();

.....

empleadosTb:Tabla=mydbs.createTable("empleados",estuctura);

if (empleadosTb==null){

      funcionOnError()

}else{

   funcionOnExito()

}


que pasarle una función de error y una función de éxito. Pero supongo que más que nada porque estoy más acostumbrado a esta última notación.
También podríamos pensar en algo 2más bizarro" que sería que la Clase AirSqlManager tenga dos variables _resultTabley _resultFuncion para poder escribir

Código :

 

var estructura:Object=new Object();

.....

if (mydbs.createTable("empleados",estuctura)!=null){

    var empleadosTb:Tabla=mydbs.resultTable

}


Para eso usaríamos la función "get" de "resultTable" para devolver una copia de _resultTable y poner dicho valor a nulo.
Por: Eliseo-blog
Deja un comentario
IMPORTANTE

Recuerda ser respetuoso, no insultes a otras personas, ni uses palabrotas, hay una persona al otro lado de la pantalla.

Habla bien, NO ESCRIBAS EN MAYUSCULA TODO, no escribas como en un SMS, evita cosas como "ke", "x q" y demás abreviaciones.

Aquí funcionan las etiquetas de los foros, puedes usar [b] para negrita, [img] para las imágenes, [url] para los enlaces, etc.

Si tienes preguntas técnicas, envíalas mejor al foro.