Cristalab

                 ¿Quieres registrarte?

Cómo conectar AIR con una base de datos SQLite

Por: Zandy
14 de Noviembre del 2007
873 de clabLevel
Otros artículos de Zandy
9,645 visitas

En este tip explicaré brevemente cómo interactúa Adobe AIR con una base de datos SQLite, que es la que viene embebida con él. Gracias a ella, tenemos una herramienta potente para manejar datos en el sistema local sin tener que usar programas como MDMZinc o un lenguaje de servidor. Para explicar este tip crearé una simple aplicación AIR con Flex que insertara, y mostrara datos de una BD.

Lo primero será establecer conexión con la BD. Para ello, usaremos el siguiente código, que está explicado en los comentarios:

Código :

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
   creationComplete="init()" width="439" height="406" xmlns:local="*">
   <mx:Script>
      <![CDATA[
                import mx.controls.Alert; 
                import mx.collections.ArrayCollection;
                import flash.events.SQLEvent; //Evento que maneja las operaciones de los objetos SQLConnection o SQLStatement

                private var conn:SQLConnection; //Objeto que me permite hacer abrir la conexion con la BD.
                private var BDFile:File; //Variable que abrira y/o creara la bd.
                [Bindable] public var myDP:ArrayCollection;

                public function init()
                {
                         conn = new SQLConnection(); //Creo el objeto de conexion
   
                        //Listener del objeto connection para cuando se abrio la conexion con éxito
                       conn.addEventListener(SQLEvent.OPEN, 
                       function(event:SQLEvent):void
              {
               Alert.show("La conexion se realizo con exito :-)");
                    });
                       //Listener para cuando la conexion fallo
                  conn.addEventListener(SQLErrorEvent.ERROR, 
             function(event:SQLErrorEvent):void
             {
                Alert.show("Error de conexion --> "+event.error.message);
             });            

                      //Esta instruccion lo que me permite es abrir[si existe] o crear el fichero en el directorio de la aplicación.
                      BDFile = new File(File.applicationResourceDirectory.nativePath+"\\agenda.db"); 

                      conn.open(BDFile); //Le digo al objeto connection que abra el File.
}
</mx:WindowedApplication>



Si todo ha ido bien, el resultado debería ser el siguiente.



Noten que si el fichero agenda.db no existe, AIR lo crea, y si no, lo abre.

Ahora crearemos una función que nos construirá la estructura de la BD cuando el fichero no exista, es decir, para cuando se crea por primera vez.

Primero importamos un par de clases que nos harán falta para eso.

Código :

// Se usa para ejecutar una sentencia SQL en una BD que esta abierta con SQLConnection
                        import flash.data.SQLStatement;
                        private function createTable():void{
            
            var createObj:SQLStatement = new SQLStatement();  
            var strSQL:String = new String(); //Query de crear tabla
            strSQL = "CREATE TABLE IF NOT EXISTS datos(";
            strSQL += "user_id INTEGER PRIMARY KEY AUTOINCREMENT,";
            strSQL += "name TEXT,";
            strSQL += "adress TEXT,";
            strSQL += "phone NUMERIC";
            strSQL += ")";
            createObj.text = strSQL; //paso la query a SQLStatement.
                        
            createObj.sqlConnection = conn; //Paso la conexión.
            createObj.addEventListener(SQLEvent.RESULT,
               function(event:SQLEvent):void
               {
                  showData();
               });   
            createObj.addEventListener(SQLErrorEvent.ERROR, 
               function(event:SQLErrorEvent):void
               {
                  Alert.show("No se pudo crear la tabla ---> "+event.error.message);
               });         
                     
         createObj.execute(); //Ejecuto la query [la de crear tabla]
         }


A esta función debes llamarla desde el SQLEvent.OPEN de la función init.

Creamos una clase llamada datosVO, que no es mas que un valueObject que nos servirá solo para puro tramite de datos.

datosVo.as :

Código :

package
{
[Bindable]   
   public class datosVO
   {
      public var _name:String;
      public var _adress:String;
      public var _phone:uint;
   }
}


Ahora haremos un par de funciones más, una para hacer el INSERT y otra que nos hará el SELECT para llenar a myDB y mostrarlo en la vista:

Código :

              private function showData():void{
            var selectObj:SQLStatement = new SQLStatement();
            selectObj.sqlConnection = conn;  
            var strSQL:String = "SELECT user_id, name,adress, phone FROM datos"; 
            selectObj.text = strSQL; 
            
            selectObj.addEventListener(SQLEvent.RESULT,
               function(event:SQLEvent):void
               {
                  var res = (event.target as SQLStatement).getResult();
                  myDP = new ArrayCollection(res.data);
               });
            selectObj.addEventListener(SQLErrorEvent.ERROR, 
               function(event:SQLErrorEvent):void
               {
                  Alert.show("Result Error - "+event.error.message);
               });   
            selectObj.execute();
         }
         
         private function insertData(data:datosVO):void
         {
            var insertObj:SQLStatement = new SQLStatement(); //Creo el objeto SQLStatement.
            insertObj.sqlConnection = conn; //Le paso la conexion al objeto SQLStatement.
            var strSQL:String = new String();
            //Asigno el query...
            strSQL = "INSERT INTO datos (name, adress, phone) ";
            strSQL += "VALUES ('"+data._name+"','"+data._adress+"',"+data._phone+")";
            insertObj.text = strSQL; //le asigno la query al objeto SQLStatement.
            
            //Si paso algo, se ejecuta esta funcion.
            insertObj.addEventListener(SQLErrorEvent.ERROR,
               function(event:SQLErrorEvent):void{
                  Alert.show("No se pudo insertar los datos ---> "+event.error.message);
               }
            );         
            //Si se pudo efectuar la operacion se ejecuta esta funcion
            insertObj.addEventListener(SQLEvent.RESULT,
               function(event:SQLEvent):void{
                  //Como se que se inserto correctamente, actualizo el provider local..
                  myDP.addItem({name:data._name, adress:data._adress, phone:data._phone});
                  //Borro el formulario.. :-)
                  name_txt.text = "";
                  adress_txt.text = "";
                  phone_txt.text = "";
               }
            );      
            insertObj.execute(); //Ejecuto la query
         }


Bien ahora vayamos al mxml y hagamos nuestra simple vista.

Código :

<local:datosVO id="datosTemp">
      <local:_adress>{ adress_txt.text }</local:_adress>
      <local:_name>{ name_txt.text }</local:_name>
      <local:_phone>{ int(phone_txt.text) }</local:_phone>
   </local:datosVO>
   
   <mx:DataGrid x="10" y="10" width="399" height="248" id="datos" dataProvider="{ myDP }">
      <mx:columns>
         <mx:DataGridColumn headerText="Column 1" dataField="name"/>
         <mx:DataGridColumn headerText="Column 2" dataField="adress"/>
         <mx:DataGridColumn headerText="Column 3" dataField="phone"/>
      </mx:columns>
   </mx:DataGrid>
   <mx:Button x="10" y="362" label="Insertar" click="{ insertData(datosTemp) }" />
   <mx:TextInput x="87.5" y="266" id="name_txt"/>
   <mx:TextInput x="87.5" y="296" id="adress_txt"/>
   <mx:TextInput x="87.5" y="328" id="phone_txt"/>
   <mx:Label x="10" y="268" text="Nombre"/>
   <mx:Label x="10" y="298" text="Direccion"/>
   <mx:Label x="10" y="330" text="Telefono"/>


Y todo listo.

Codigo completo:

Código :

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
   creationComplete="init()" width="439" height="406" xmlns:local="*">
   <mx:Script>
      <![CDATA[
         import mx.controls.Alert; 
         import mx.collections.ArrayCollection;
         //Evento que maneja las operaciones de los objetos SQLConnection o SQLStatement
         import flash.events.SQLEvent; 
         
         //Objeto que me permite hacer abrir la conexion con la BD.
         private var conn:SQLConnection;
         
         //Variable que abrira y/o creara la bd.
         private var BDFile:File;
         
         [Bindable] public var myDP:ArrayCollection;
         
         public function init()
         {
         conn = new SQLConnection(); //Creo el objeto de conexion
            
            //Listener del objeto connection para cuando se abrio la conexion con éxito se vaya a la función onSuccess
            conn.addEventListener(SQLEvent.OPEN, 
               function(event:SQLEvent):void
               {
                  createTable();
               });
            //Listener para cuando la conexion fallo se vaya a la función onError
            conn.addEventListener(SQLErrorEvent.ERROR, 
               function(event:SQLErrorEvent):void
               {
                  Alert.show("Error de conexion --> "+event.error.message);
               });            
         //Esta instruccion lo que me permite es abrir[si existe] o crear el fichero en el directorio de la aplicación.
         BDFile = new File(File.applicationResourceDirectory.nativePath+"\\agenda.db");
         
         //Le digo al objeto connection que abra el File.
         conn.open(BDFile);
         }         
         
         private function showData():void{
            var selectObj:SQLStatement = new SQLStatement();
            selectObj.sqlConnection = conn;  
            var strSQL:String = "SELECT user_id, name,adress, phone FROM datos"; 
            selectObj.text = strSQL; 
            
            selectObj.addEventListener(SQLEvent.RESULT,
               function(event:SQLEvent):void
               {
                  var res = (event.target as SQLStatement).getResult();
                  myDP = new ArrayCollection(res.data);
               });
            selectObj.addEventListener(SQLErrorEvent.ERROR, 
               function(event:SQLErrorEvent):void
               {
                  Alert.show("Result Error - "+event.error.message);
               });   
            selectObj.execute();
         }
         
         private function insertData(data:datosVO):void
         {
            var insertObj:SQLStatement = new SQLStatement(); //Creo el objeto SQLStatement.
            insertObj.sqlConnection = conn; //Le paso la conexion al objeto SQLStatement.
            var strSQL:String = new String();
            //Asigno el query...
            strSQL = "INSERT INTO datos (name, adress, phone) ";
            strSQL += "VALUES ('"+data._name+"','"+data._adress+"',"+data._phone+")";
            insertObj.text = strSQL; //le asigno la query al objeto SQLStatement.
            
            //Si paso algo, se ejecuta esta funcion.
            insertObj.addEventListener(SQLErrorEvent.ERROR,
               function(event:SQLErrorEvent):void{
                  Alert.show("No se pudo insertar los datos ---> "+event.error.message);
               }
            );         
            //Si se pudo efectuar la operacion se ejecuta esta funcion
            insertObj.addEventListener(SQLEvent.RESULT,
               function(event:SQLEvent):void{
                  //Como se que se inserto correctamente, actualizo el provider local..
                  myDP.addItem({name:data._name, adress:data._adress, phone:data._phone});
                  //Borro el formulario.. :-)
                  name_txt.text = "";
                  adress_txt.text = "";
                  phone_txt.text = "";
               }
            );      
            insertObj.execute(); //Ejecuto la query
         }
         
         private function createTable():void{
            
            var createObj:SQLStatement = new SQLStatement();  
            var strSQL:String = new String(); //Query de crear tabla
            strSQL = "CREATE TABLE IF NOT EXISTS datos(";
            strSQL += "user_id INTEGER PRIMARY KEY AUTOINCREMENT,";
            strSQL += "name TEXT,";
            strSQL += "adress TEXT,";
            strSQL += "phone NUMERIC";
            strSQL += ")";
            createObj.text = strSQL; //paso la query a SQLStatement.
                        
            createObj.sqlConnection = conn; //Paso la conexión.
            createObj.addEventListener(SQLEvent.RESULT,
               function(event:SQLEvent):void
               {
                  showData();
               });   
            createObj.addEventListener(SQLErrorEvent.ERROR, 
               function(event:SQLErrorEvent):void
               {
                  Alert.show("No se pudo crear la tabla ---> "+event.error.message);
               });         
                     
         createObj.execute(); //Ejecuto la query [la de crear tabla]
         }

      ]]>
   </mx:Script>
   
   <local:datosVO id="datosTemp">
      <local:_adress>{ adress_txt.text }</local:_adress>
      <local:_name>{ name_txt.text }</local:_name>
      <local:_phone>{ int(phone_txt.text) }</local:_phone>
   </local:datosVO>
   
   <mx:DataGrid x="10" y="10" width="399" height="248" id="datos" dataProvider="{ myDP }">
      <mx:columns>
         <mx:DataGridColumn headerText="Column 1" dataField="name"/>
         <mx:DataGridColumn headerText="Column 2" dataField="adress"/>
         <mx:DataGridColumn headerText="Column 3" dataField="phone"/>
      </mx:columns>
   </mx:DataGrid>
   <mx:Button x="10" y="362" label="Insertar" click="{ insertData(datosTemp) }" />
   <mx:TextInput x="87.5" y="266" id="name_txt"/>
   <mx:TextInput x="87.5" y="296" id="adress_txt"/>
   <mx:TextInput x="87.5" y="328" id="phone_txt"/>
   <mx:Label x="10" y="268" text="Nombre"/>
   <mx:Label x="10" y="298" text="Direccion"/>
   <mx:Label x="10" y="330" text="Telefono"/>
</mx:WindowedApplication>


Espero les sirva de base para continuar con este tema.

Aquí tienen algunos links para investigar mas:


Saludos.


Artículos Relacionados


Etiquetas flex apollo

Comentarios | Enviar un comentario
Muy buen tip, y muy útil ;)
Por: Zah
excelente!!! muy bueno ^^ , eso me recuerda q debno actualizar los tutos de AIR :S
Por: eldervaz
Genial!!! justo lo que necesitaba para empezar con AIR ^^

Excelente tip Joris Van Spilbergen! ^^
Por: master_of_puppetz
Espero que pronto publiquen ejemplos para air desde el entorno flash
Por: Alrevez_blog
Excelente Joris Van Spilbergen... Hace Rato quería ver algo así. Muchas Gracias.
Por: AXM
excelente !!!
Por: nico_blog
mi heroe gracias spilberg, esta genial, ahora si flash es un sistema de verdad
Por: Chris_blog
buena !! ^^ esto me trae recuerdos de .NET :o ahora a trabajar directo con las Query en AS3 ^^
Gracias Total !!! :wink:
Por: Otaku RzO
alguien tiene idea si piensan sacar algo para conectarse directamente a un MS SQLSERVER?
Por: crimson14
Una pregunta, ¿se puede utilizar ODBC con Air?
Por: rodia
se puede hacer esto sin AIR? o sea con un mxml comun? porque seria un golazo!
Por: demiantriebl_blog
Hola. Excelente artículo, me sirvió para comenzar con Flex SQLite, pero quisiera aportar algo. FLEX/AIR puede acceder a la base de datos SQLite de forma sincrónica o asincrónica, para muchos casos, yo creo que la mayoría, donde las bases de datos serian pequeñas y las transacciones no tomarian mucho tiempo, la forma sincrónica es más facil de implementar pues no se necesitan declarar "escuchadores" o listeners. De hecho en los ejemplos que amablemente nos das usas la forma sincrónica por lo que no sería necesario los listeners, aunque, por supuesto, se pueden usar... por ejemplo para la función de showData() podría quedar así:

public function showData():void{
var selectObj:SQLStatement = new SQLStatement();
selectObj.sqlConnection = conn;
var strSQL:String = "SELECT user_id, name,adress, phone FROM datos";
selectObj.text = strSQL;
selectObj.execute();
var result:SQLResult = selectObj.getResult();
}

¡Saludos!
Por: Ramsés Moreno_blog
Se me pasó comentar solo que la unica diferencia para establecer que la conexión será sincrónica o asincrónica es el método open:

Sincrónico: conn.open(BDFile);
Asincrónico: conn.openAsync(BDFile);
Por: Ramsés Moreno_blog
Excelente, gran ayuda.
Muchas gracias Joris Van Spilbergen
Por: JC_blog
Muchas Gracias.
Sencillo y claro.
Muy util.
Por: Rafa Hernández-blog
quisiera saber como enlazar una base de datos de visual basic a un txt, por ejemplo un bloc de notas
Por: rui:costa-blog
Hola, ojala y me pueda ayudar alguien, soy novatisimo en air y necesito hacer un dc interactivo en flash pero que lleve una agenda y respoder unos examenes la cuestion es que tiene que ir guardadno intendos, nombre, calificaciones, etc y pense en usar air porque tengo unos tutos para poner animaciones swf en aplicaciones air ahora lo que me falta es la base para los examenes, pero ya corri el primer cuadro de codigo y me marca en la linea conde abre si existe o crea el fichero en el directorio de la aplicacion me dice esto:


1119: Acceso a una propiedad applicationResourceDirectory posiblemente no definida mediante una referencia con tipo estático Class. pruebaDB/src pruebaDB.mxml line 32 1245453972720 28
Por: tergon
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.