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.. )
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.
- 1-El objeto con la información para crear la tabla.
- 2-La función a la que llama si se pudo crear la tabla o si ya existe.
- 3-La función a la que llama si se genero algun error en la creación de la tabla.
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.
- 1-El objeto con la información para hacer el insert.
- 2-La función a la que llama si se pudo hacer. (todabía no se como recuperar el ultimo id)
- 3-La función a la que llama si se genero algun error.
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.
- 1-El objeto con la información para hacer la consulta.
- 2-La función a la que llama si se pudo hacer. devuelve un Array de objetos con el resultado
- 3-La función a la que llama si se genero algún error.
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.
- 1-El objeto con la información del registro que se va a modificar.
- 2-La función a la que llama si se pudo hacer.
- 3-La función a la que llama si se genero algun error.
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.
¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.
Por AXM el 26 de Marzo de 2009
Por eldervaz el 26 de Marzo de 2009
Por phoxer el 26 de Marzo de 2009
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 Zguillez el 26 de Marzo de 2009
intentaremos optimizarla para hacerla más manejable
Por Raxiro el 26 de Marzo de 2009
sets=sets.substring(0,sets.length-1);
No es lo mismo que esto:
sets=sets.substr(0,-1);
Bueno nuevamente muy bueno!
Por phoxer el 26 de Marzo de 2009
@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 Raxiro el 27 de Marzo de 2009
Por phoxer el 27 de Marzo de 2009
Raxiro-blog :
Cualquier aporte con buenas intenciones e incluso para mejorar el rendimiento, como es en tu caso, es valido..
Gracias.
Por andres felipe el 27 de Marzo de 2009
gracias
Por bubudrc el 27 de Marzo de 2009
Por GersonM_17 el 02 de Abril de 2009
Te haré llegar algunas modificaciones
Por Eliseo el 03 de Abril de 2009
Código :
Por otra parte me haría una Clase "Tabla", de modo que createTable sería más o menos
Código :
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 :
Claro que cambia todo un poco, pero un programa podría ser más o menos
Código :
Por phoxer el 07 de Abril de 2009
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 :
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 Eliseo el 07 de Abril de 2009
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 :
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 :
Para eso usaríamos la función "get" de "resultTable" para devolver una copia de _resultTable y poner dicho valor a nulo.
Por Statukuo el 12 de Julio de 2010
Espero que a alguien se le ocurra algo, a mi se me han acabado las ideas...
Por CLAnonimo el 21 de Septiembre de 2010
Por Yom_24 el 16 de Diciembre de 2010
Disculpen estoy iniciandome en todo esto del ActionScript3 quisiera saber si puedo trabajar este codigo directamente desde Flash Builder 4, o tendria que hacerlo en Adobe Flash en especifico tal vez suene una pregunta tonta pero disculpen no tengo idea de como aplicarlo.
Gracias!.