Record collection (JavaScript) Creació d'una aplicació amb una base de dades per ordenar una col·lecció de música Projecte de documentació del GNOME gnome-doc-list@gnome.org Johannes Schmid jhs@gnome.org Marta Maria Casetti mmcasettii@gmail.com 2013 Record collection

En aquest programa d'aprenentatge aprendreu a:

Connectar-se a una base de dades amb la libgda

Inserir i navegar registres a una taula d'una base de dades

Introducció

Aquesta demostració utilitza el llenguatge JavaScript. Es mostrarà com connectar-se i utilitzar una base de dades des d'un programa escrit amb la GTK+ a través de la biblioteca GDA (Accés a dades del GNOME). Haureu d'instalar-la per poder seguir aquesta demostració.

El propòsit de la biblioteca GDA (Accés a dades del GNOME) és proporcionar un accés universal a diferents estils i tipus de fonts de dades. Això compren des dels sistemes tradicionals de bases de dades relacions fins a qualsevol tipus de font de dades imaginable com ara un servidor de correu, un directori d'LDAP, etc. Per més informació i la documentació completa de l'API, aneu al lloc web de la GDA.

Tot i que una gran part del codi està dedicat a la interfície d'usuari (GUI), el programa d'aprenentatge està centrat en les parts relacionades amb la base de dades (es farà menció d'altres parts si es consideren rellevants). Per veure més programes escrits en JavaScript pel GNOME, vegeu el programa d'aprenentatge del programa de visualització d'imatges.

Creació d'un projecte a l'Anjuta

Abans de començar a programar, heu de crear un projecte nou a l'Anjuta. L'Anjuta crearà tots els fitxers necessaris per, més endavant, construir i executar el codi. És molt útil per així mantenir-ho tot junt.

Inicieu l'Anjuta i feu clic a FitxerNouProjecte per obrir l'auxiliar de projectes.

Trieu JavaScript genèric a la pestanya JS, feu clic a Continua i empleneu les dades de les pàgines següents de l'auxiliar. Utilitzeu record-collection com a nom de projecte i de directori.

Feu clic a Aplica i es crearà el projecte. Obriu el fitxer src/main.js des de la pestanya de Projecte o de Fitxer. El fitxer ja conté un exemple de codi molt bàsic.

Estructura del programa

Aquesta demostració és una aplicació de GTK+ senzilla (amb una sola finestra) que permet inserir registres a una taula d'una base de dades, així com navegar pels registres d'aquesta. La taula conté dos camps: id, per desar nombres enters i name per desar text de llargada variable. La primera secció (al principi) de l'aplicació permet inserir registres a la taula. La secció de baix (al final) permet veure tots els registres de la taula. S'actualitza el contingut de la taula cada vegada que s'afegeix un registre nou i també quan s'inicia l'aplicació.

Ara comença lo bo

Primera ullada a l'esquelet del programa:

Línies 1 a 4: importacions inicials. Mireu-vos bé la línia 3 que li diu al JavaScript que importi la biblioteca GDA, la biblioteca central d'aquest programa d'aprenentatge.

Línies 6 a 17: defineixen la classe Demo. Mireu-vos bé les línies 13 a 15, on es criden als 3 mètodes que faran tota la feina i que es descriuran tot seguit.

Línies 19 a 23: inicien l'aplicació.

Disseny de l'aplicació

Feu una ullada al mètode setupWindow. És el responsable de crear la interfície d'usuari (UI). Com que la interfície no és l'eix principal del programa d'aprenentatge només es comenta per sobre.

Insert a record", xalign: 0, use_markup: true}); main_box.pack_start (info1, false, false, 5); // "insert a record" horizontal box var insert_box = new Gtk.Box ({orientation: Gtk.Orientation.HORIZONTAL, spacing: 5}); main_box.pack_start (insert_box, false, false, 5); // ID field insert_box.pack_start (new Gtk.Label ({label: "ID:"}), false, false, 5); this.id_entry = new Gtk.Entry (); insert_box.pack_start (this.id_entry, false, false, 5); // Name field insert_box.pack_start (new Gtk.Label ({label: "Name:"}), false, false, 5); this.name_entry = new Gtk.Entry ({activates_default: true}); insert_box.pack_start (this.name_entry, true, true, 5); // Insert button var insert_button = new Gtk.Button ({label: "Insert", can_default: true}); insert_button.connect ("clicked", Lang.bind (this, this._insertClicked)); insert_box.pack_start (insert_button, false, false, 5); insert_button.grab_default (); // Browse textview var info2 = new Gtk.Label ({label: "Browse the table", xalign: 0, use_markup: true}); main_box.pack_start (info2, false, false, 5); this.text = new Gtk.TextView ({editable: false}); var sw = new Gtk.ScrolledWindow ({shadow_type:Gtk.ShadowType.IN}); sw.add (this.text); main_box.pack_start (sw, true, true, 5); this.count_label = new Gtk.Label ({label: "", xalign: 0, use_markup: true}); main_box.pack_start (this.count_label, false, false, 0); this.window.show_all (); },]]>

Línies 22 i 27: creen dues entrades (per als dos camps) on els usuaris de l'aplicació escriuran alguna cosa per inserir-la a la base de dades.

Línies 31 a 34: creen el botó d'inserció. Es connecta el seu senyal clicked al mètode de classe privat _insertClicked. Aquest mètode es descriu més endavant.

Línia 30: crea el giny (TextView) on es mostrarà el contingut de la taula.

Línia 44: crea l'etiqueta on es mostrarà el nombre de registres de la taula. Inicialment serà buit, s'actualitzarà més endavant.

Connexió i inicialització de la base de dades

El codi per connectar a la base de dades és en el mètode setupDatabase que segueix:

Línies 2 i 3: creen l'objecte Connection de la GDA. S'han de proporcionar unes quantes propietats en el seu constructor:

provider: un dels proveïdors amb els que la GDA permet treballar. Són: SQLite, MySQL, PostgreSQL, Oracle i molts d'altres. Per aquesta demostració utilitzarem la base de dades SQLite ja que ve per defecte en la majoria de distribucions i és senzilla de treballar-hi (només fa servir un fitxer com a base de dades).

cnc_string: la cadena de connexió. Pot canviar segons el proveïdor. La sintaxi per a l'SQLite és: DB_DIR=CAMÍ;DB_NAME=NOM_DE_FITXER. En aquesta demostració farem servir una base de dades anomenada gnome_demo a la carpeta de l'usuari (adoneu-vos de la crida a la funció get_home_dir de la GLib).

Si la GDA no sap treballar amb el proveïdor o si a la cadena de connexió li manca algun element, la línia 2 generarà una excepció, de manera que en codi real hauríem de gestionar-ho amb la sentència de JavaScript try...catch.

Línia 4: obre la connexió. Si no existeix la base dades el proveïdor de SQLite la crearà en aquest moment.

Línies 6 a 10: es realitza un «SELECT» simple per comprovar si existeix la taula (línia 7). Si no existeix (perquè s'acaba de crear la base de dades), aquesta línia generarà una excepció que es gestionarà en el bloc de codi try...catch. Si és el cas, s'executa la sentència per crear la taula (línia 9).

In order to run the SQL commands above we are using the GDA connection methods execute_select_command and execute_non_select_command. They are simple to use, and just require two arguments: The Connection object and the SQL command to be parsed.

En aquest punt d'execució la base de dades ja està configurada i a punt per utilitzar-se.

Selecció

Després de connectar-se a la base de dades, el constructor de la demostració crida el mètode selectData. Aquest mètode és el responsable d'obtenir els registres de la taula i mostrar-los en el giny TextView. Ara es comentarà amb més detall:

\t" + name_field + '\n'; } this.text.buffer.text = text; this.count_label.label = "" + dm.get_n_rows () + " record(s)"; },]]>

Line 2: The SELECT command. We are using the GDA connection's execute_select_command method for that. It returns a DataModel object, which is later used to retrieve the rows.

Línia 3: crea l'objecte Iter que s'utilitza per iterar sobre els registres de DataModel.

Línia 7: itera sobre tots els registres, els recupera amb l'ajuda de l'objecte Iter. En aquest punt la variable iter conté les dades actuals recuperades de la base de dades. El seu mètode move_next retorna false quan arriba a l'últim registre.

Línies 8 i 9: es fan dues coses a cada línia:

S'utilitza el mètode get_value_at d'Iter que només necessita un paràmetre: el número de la columna a recuperar, començant a partir de zero. Com que el SELECT que s'ha fet només retorna dues columnes, els índexs de les columnes són el 0 i l'1.

El mètode get_value_at retorna el camp en el format GValue de la GLib. Una manera senzilla de convertir aquest format a una cadena és utilitzant la funció global de la GDA value_stringify. Això és el que es fa aquí i després es desa el resultat a les variables id_field i name_field.

Línia 11: es concatenen els dos camps per fer una sola línia de text separada per "=>" i desada a la variable text.

Línia 14: quan s'acaba la iteració, hi ha tots els registres formatats a la variable text. En aquesta línia només s'estableix que el contingut de TextView sigui el d'aquesta variable.

Línia 15: mostra el nombre de registres de la taula amb el mètode get_n_rows de DataModel.

Inserció

Fins ara s'ha connectat a la base de dades i s'ha mostrat com seleccionar les files de la taula. Ara només falta fer un INSERT a la taula. Recordeu que abans en el mètode setupWindow s'ha connectat el senyal clicked del botó Insert amb el mètode _insertClicked? Ara se'n mostra la implementació.

We have learned how to use the GDA connection's methods execute_select_command and execute_non_select_command to quickly execute SQL commands on the database. GDA allows one to build a SQL statement indirectly, by using its SqlBuilder object. What are the benefits of this? GDA will generate the SQL statement dynamically, and it will be valid for the connection provider used (it will use the same SQL dialect the provider uses). Let's study the code:

Línies 2 i 3: comproven que l'usuari hagi emplenat tots els camps. El codi del mètode privat _validateFields és molt senzill i li podeu fer una ullada en el codi font sencer de la demostració.

Línia 5: la forma ràpida de fer un INSERT. Està comentat perquè es vol mostrar com utilitzar l'objecte SqlBuilder per construir una ordre SQL que sigui vàlida per qualsevol base de dades.

Línia 7: crea l'objecte SqlBuilder. S'ha d'informar del tipus d'ordre que es vol construir. Pot ser un SELECT, un UPDATE, un INSERT o bé un DELETE.

Línia 8: estableix el nom de la taula on s'efectuarà l'ordre (generarà un INSERT INTO demo)

Línies 9 i 10: estableix els camps i els valors que formaran part de l'ordre. El primer argument és el nom del camp (tal i com està definit a la taula). El segon argument és el valor que li volem donar.

Línia 11: s'obté l'objecte generat dinàmicament Statement que representa una ordre SQL.

Línia 12: ara ja sí, s'executa l'ordre SQL (un INSERT).

Línia 14: es netegen els camps id i nom de la pantalla. El codi del mètode privat _clearFields és molt senzill i es pot trobar en el codi font sencer de la demostració.

Línia 15: actualitza la vista de la pantalla fent un altre SELECT.

També es poden utilitzar paràmetres mentre construïu l'ordre. Pel fet d'utilitzar objectes SqlBuilder i els seus paràmetres es poden evitar atacs d'injecció d'SQL. Per més informació sobre els paràmetres mireu-vos la documentació de la GDA.

Execució de l'aplicació

Ja s'ha vist tot el codi que fa falta, així que ja es pot executar el codi. S'acaba de crear una aplicació per la gestió d'una col·lecció de música!

Implementació de referència

Si teniu algun problema amb el programa d'aprenentatge, compareu el codi amb el codi de referència.