Com fer servir Java, JDBC i GNU/Linux
dissabte, abril 25th, 2009A la facultat ens han donat instruccions per a treballar amb Java i JDBC des de Windows. Com que alguns no fem servir aquest sistema inoperatiu per motius tant tècnics com ètics, m’hi he barallat una estoneta i he trobat com fer-ho amb GNU/Linux. No és complicat
Entorn
Java
Primer de tot ens cal l’entorn per desenvolupar aplicacions en Java
apt-get install sun-java6-jdk
Amb això no n’hi ha prou per fer un Hello World. GNU/Linux permet tenir diverses màquines virtuals instal·lades, i per defecte en ve una de lliure (cosa que ja em sembla bé). Volem desenvolupar en un entorn tan semblat a la facultat com sigui possible, així que ens toca canviar la màquina virtual i posar la privativa:
artoo:/home/edu# update-alternatives --config java
Hi ha 3 alternatives que proveeixin «java».
Selecció Alternativa
-----------------------------------------------
1 /usr/bin/gij-4.3
+ 2 /usr/lib/jvm/java-gcj/jre/bin/java
* 3 /usr/lib/jvm/java-6-sun/jre/bin/java
Premeu retorn per a mantenir l'opció per defecte[*], o introduïu un número de selecció:
Volem la 3.
Per treballar amb JDBC i PostgreSQL ens fa falta el driver adequat. A dia d’avui n’hi ha dos de disponibles, el 3 i el 4. Jo he necessitat el 4 perquè tinc màquina virtual versió >= 1.6
edu@artoo:~/facultat/bd/java$ java -version
java version "1.6.0_12"
Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
Java HotSpot(TM) Client VM (build 11.2-b01, mixed mode, sharing)
edu@artoo:~/facultat/bd/java$
Ens baixarem un fitxer .jar, que ve a ser un tar.gz. El podem posar on vulguem, perquè després li direm al sistema on és. Jo he optat per fer-me un directori de treball per fer les pràctiques en /home/edu/facultat/bd/java :
edu@artoo:~/facultat/bd/java$ ls
classp gestioSocis.java HelloWorldApp.java
gestioSocis.class HelloWorldApp.class
edu@artoo:~/facultat/bd/java$ ls classp/
postgresql.jar
Ara ja tenim els ingredients, i falta connectar-los. Caldrà exportar la variable d’entorn CLASSPATH. Pels veterans de C++, això ve a ser com quan compilem amb g++
g++ -c programa.cpp -I/includesdiversos
Cal dir-li on cercar fitxers que inclourem i que no venen de sèrie. Com si fos una variable d’entorn normal, fem:
export CLASSPATH=.:classp/postgresql.jar
i així li diem que busqui classes en el directori actual i en classp/postgresql.jar. Ara, per fi, ja podem fer les primeres proves amb JDBC.
Servidor i PostgreSQL
Necessitem un servidor Apache i PostgreSQL. L’opció més fàcil és fer servir LAMPP :
Instal·leu lampp en /opt/lampp Instruccions i paquet
Instal·leu el plugin per a PosgreSQL Instruccions i paquet
Els passos indicats a la web del plugin són:
- “tar xfz postgresql.tar.gz -C /tmp” Canvieu el nom de fitxer pel que hagueu baixat, és clar.
- “cd /tmp/postgresql-addon”
- “./INSTALL”
Per a iniciar el servidor POSGRESQL: /opt/lampp/lampp startpostgresql
Stop: /opt/lampp/lampp stoppostgresql
combinació usuari i contrasenya per defecte: User: root Password: lampp
És recomanable iniciar primer el servidor apache: /opt/lampp/lampp start i després el posgresql: /opt/lampp/lampp startpostgresql
Podeu veure una interfície web per a Posgres des del Firefox, tot anant a l’adreça: /localhost/phppgadmin
Com compilar amb Java
Farem un HelloWorld en un segon:
class HelloWorldApp { public static void main(String[] args) { System.out.println("Hello World!"); // Display the string. } }
Aquest és el codi. Cal desar-lo en HelloWorldApp.java. És important respectar el nom de fitxer, que ha de ser igual al de la classe principal.
Doncs apa:
edu@artoo:~/facultat/bd/java$ javac HelloWorldApp.java
edu@artoo:~/facultat/bd/java$ java HelloWorldApp
Hello World!
edu@artoo:~/facultat/bd/java$
Proves amb JDBC
Per l’assignatura de Bases de Dades de la FIB, quadrimestre 08-09Primavera, fem servir el següent escenari (font)
CREATE TABLE socis (dni char(9), nom char(30) NOT NULL, telefon char(9), numVISA char(12), ciutatResidencia char(20) DEFAULT 'Barcelona', PRIMARY KEY (dni)); CREATE TABLE tipus (tipus char(15), numMaxInscripcions integer NOT NULL, PRIMARY KEY (tipus)); CREATE TABLE activitats (tipusActivitat char(15), dataInici integer, descripcio char(50) UNIQUE, dni char(9), preu integer CHECK (preu > 10), lloc char(20), ciutat char(20), PRIMARY KEY (tipusActivitat, dataInici), FOREIGN KEY (tipusActivitat) REFERENCES tipus (tipus), FOREIGN KEY (dni) REFERENCES socis); CREATE TABLE inscripcions (tipusActivitat char(15), dataInici integer, dni char(9), formaPagament char(20), dataPagament integer, CHECK (dataInici < dataPagament), PRIMARY KEY (tipusActivitat, dataInici, dni), FOREIGN KEY (tipusActivitat, dataInici) REFERENCES activitats, FOREIGN KEY (dni) REFERENCES socis);
Amb les dades a continuació (font):
INSERT INTO socis VALUES (10, 'Carme', 101,NULL, 'Hospitalet'); INSERT INTO socis VALUES (11, 'Nuria', 111, 111111, 'Hospitalet'); INSERT INTO socis VALUES (12, 'Josep', 121, 121121, 'Hospitalet'); INSERT INTO socis VALUES (13, 'Jordi', 131, 131131, 'Barcelona'); INSERT INTO socis VALUES (14, 'Imma', 141, 141141, 'Barcelona'); INSERT INTO socis VALUES (15, 'Roger', 151, 151151, 'Barcelona'); INSERT INTO socis VALUES (16, 'Oriol', 161, 161161, 'Barcelona'); INSERT INTO socis VALUES ('17', 'Mireia', 101,101101, 'Palleja'); INSERT INTO socis (dni, nom, telefon, numVISA) VALUES (19, 'Joan', 333, 333333); INSERT INTO socis (dni, nom, telefon, ciutatResidencia) VALUES (20, 'Joan', 333, 'Sant Just'); INSERT INTO tipus VALUES ('capDAny', 200); INSERT INTO tipus VALUES ('cine', 10); INSERT INTO tipus VALUES ('teatre', 6); INSERT INTO tipus VALUES ('discoteca', 30); INSERT INTO tipus VALUES ('excursio', 30); INSERT INTO tipus VALUES ('sopar', 2); INSERT INTO tipus VALUES ('opera', 6); INSERT INTO tipus VALUES ('concert', 6); INSERT INTO activitats VALUES ('cine', 124, 'One Milion Baby', 10, 17, 'Cinesa Diagonal', 'Barcelona'); INSERT INTO activitats VALUES ('cine', 224, 'Magnolias de Acero', 11, 16, 'La Farga', 'Hospitalet'); INSERT INTO activitats VALUES ('capDAny', 1224, 'Festa Roc Blanc', 12, 100, 'Plaça Major', 'Vic'); INSERT INTO activitats VALUES ('sopar', 425, 'Aniversari Josep', 12, 80, 'Can Jubany', 'Calldetenes'); INSERT INTO activitats VALUES ('teatre', 424, 'El Ratoli Viatger', 10, 15, 'Teatre Atlantida', 'Ripoll'); INSERT INTO activitats VALUES ('opera', 2345, 'La Flauta Magica', NULL, NULL, 'Liceu', 'Barcelona'); INSERT INTO activitats VALUES ('concert', 3234, 'La Casa de Vent i de Fusta', 10, NULL, NULL, 'Barcelona'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 124, 10, 'amex'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('sopar', 425, 10, 'sdfjñs'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('capDAny', 1224, 10, 'amex'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 124, 11, 'visa'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('sopar', 425, 11, 'visa'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('capDAny', 1224, 11, 'visa'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('sopar', 425, 12, 'sdfjñs'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 224, 13, 'sdfjñs'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 224, 14, 'sdfjñs'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 224, 15, 'sdfjñs'); INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 224, 16, 'sdfjñs'); INSERT INTO inscripcions VALUES ('teatre', 424, 10, 'VISA', 435); INSERT INTO inscripcions VALUES ('teatre', 424, 11, 'VISA', 435); INSERT INTO inscripcions VALUES ('teatre', 424, 12, 'VISA', 435); INSERT INTO inscripcions VALUES ('teatre', 424, 13, 'VISA', 435); INSERT INTO inscripcions VALUES ('teatre', 424, 14, 'VISA', 435); INSERT INTO inscripcions VALUES ('teatre', 424, 15, 'VISA', 435); INSERT INTO inscripcions VALUES ('teatre', 424, 16, 'VISA', 435); INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 10); INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 11); INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 12); INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 13); INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 14); INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 15);
La facultat ens facilita també un codi plantilla amb les línies indispensables per establir una connexió:
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 90 91 92 93 94 95 96 97 | import java.sql.*; import java.util.Properties; public class gestioSocis { public static void main (String args[]) { try { // carregar el driver al controlador Class.forName ("org.postgresql.Driver"); System.out.println ("Driver de PostgreSQL carregat correctament."); // connectar a la base de dades // cal modificar el username, password i el nom de la base de dades // en el servidor postgresfib, SEMPRE el SSL ha de ser true Properties props = new Properties(); props.setProperty("user","elMeuNomUsuari"); props.setProperty("password","elMeuPassword"); props.setProperty("ssl","true"); props.setProperty("sslfactory", "org.postgresql.ssl.NonValidatingFactory"); Connection c = DriverManager.getConnection("jdbc:postgresql://postgresfib.fib.upc.es:5432/laMevaBaseDeDades", props); c.setAutoCommit(false); System.out.println ("Connexio realitzada correctament."); // canvi de l'esquema per defecte a un altre esquema Statement s = c.createStatement(); s.executeUpdate("set search_path to elMeuEsquema;"); s.close(); System.out.println ("Canvi d'esquema realitzat correctament."); // consultar tots les socis que viuen a Hospitalet // Dir quantes inscripcions té cada un String cR = "Hospitalet"; String consSocis="select dni,nom from socis "+ "where ciutatResidencia = '"+cR+"';"; System.out.println (consSocis); s = c.createStatement(); ResultSet r = s.executeQuery (consSocis); String consInscr="select count(*) as numInscr "+ "from inscripcions i where i.dni = ? ;"; System.out.println (consInscr); PreparedStatement ps = c.prepareStatement(consInscr); ResultSet rs = null; int quantsSocis = 0; String dni=" "; String nom=" "; while (r.next()) { quantsSocis = quantsSocis + 1; dni = r.getString("dni"); nom = r.getString("nom"); System.out.print ("El soci amb dni "+dni+" i nom "); if (nom==null) { System.out.print ("null"); } else { System.out.print (nom); } ps.setString(1,dni); rs = ps.executeQuery(); rs.next(); System.out.print("te "); System.out.print (rs.getInt("numInscr")); System.out.println(" inscripcions"); rs.close(); } r.close(); System.out.println ("Nombre de socis consultats "+quantsSocis); s.close(); // Inserir una activitat s = c.createStatement(); String inserirAct="insert into activitats "+ "values ('concert', 3250, 'El fantasma del museu', 10, 120, 'Romea', 'Barcelona')"; s.executeUpdate(inserirAct); System.out.println ("Una activitat inserida"); s.close(); // Rollback i desconnexió de la base de dades c.rollback(); c.close(); System.out.println ("Rollback i desconnexio realitzats correctament."); } catch (ClassNotFoundException ce) { System.out.println ("Error al carregar el driver"); } catch (SQLException se) { System.out.println (se.getSQLState()); System.out.println (se.getMessage()); } } } |
El que passa és que està preparat per connectar-se des dels laboratoris de la uni, i a casa vull treballar en local. M’ho modifico:
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 90 91 92 93 94 95 96 97 | import java.sql.*; import java.util.Properties; public class gestioSocis { public static void main (String args[]) { try { // carregar el driver al controlador Class.forName ("org.postgresql.Driver"); System.out.println ("Driver de PostgreSQL carregat correctament."); // connectar a la base de dades // cal modificar el username, password i el nom de la base de dades // en el servidor postgresfib, SEMPRE el SSL ha de ser true Properties props = new Properties(); props.setProperty("user","root"); props.setProperty("password","lampp"); //props.setProperty("ssl","true"); //props.setProperty("sslfactory", "org.postgresql.ssl.NonValidatingFactory"); Connection c = DriverManager.getConnection("jdbc:postgresql://localhost/javafib", props); c.setAutoCommit(false); System.out.println ("Connexio realitzada correctament."); // canvi de l'esquema per defecte a un altre esquema Statement s = c.createStatement(); s.executeUpdate("set search_path to public;"); s.close(); System.out.println ("Canvi d'esquema realitzat correctament."); // consultar tots les socis que viuen a Hospitalet // Dir quantes inscripcions té cada un String cR = "Hospitalet"; String consSocis="select dni,nom from socis "+ "where ciutatResidencia = '"+cR+"';"; System.out.println (consSocis); s = c.createStatement(); ResultSet r = s.executeQuery (consSocis); String consInscr="select count(*) as numInscr "+ "from inscripcions i where i.dni = ? ;"; System.out.println (consInscr); PreparedStatement ps = c.prepareStatement(consInscr); ResultSet rs = null; int quantsSocis = 0; String dni=" "; String nom=" "; while (r.next()) { quantsSocis = quantsSocis + 1; dni = r.getString("dni"); nom = r.getString("nom"); System.out.print ("El soci amb dni "+dni+" i nom "); if (nom==null) { System.out.print ("null"); } else { System.out.print (nom); } ps.setString(1,dni); rs = ps.executeQuery(); rs.next(); System.out.print("te "); System.out.print (rs.getInt("numInscr")); System.out.println(" inscripcions"); rs.close(); } r.close(); System.out.println ("Nombre de socis consultats "+quantsSocis); s.close(); // Inserir una activitat s = c.createStatement(); String inserirAct="insert into activitats "+ "values ('concert', 3250, 'El fantasma del museu', 10, 120, 'Romea', 'Barcelona')"; s.executeUpdate(inserirAct); System.out.println ("Una activitat inserida"); s.close(); // Rollback i desconnexió de la base de dades c.rollback(); c.close(); System.out.println ("Rollback i desconnexio realitzats correctament."); } catch (ClassNotFoundException ce) { System.out.println ("Error al carregar el driver"); } catch (SQLException se) { System.out.println (se.getSQLState()); System.out.println (se.getMessage()); } } } |
i es fa la màgia
edu@artoo:~/facultat/bd/java$ java gestioSocis
Driver de PostgreSQL carregat correctament.
Connexio realitzada correctament.
Canvi d'esquema realitzat correctament.
select dni,nom from socis where ciutatResidencia = 'Hospitalet';
select count(*) as numInscr from inscripcions i where i.dni = ? ;
El soci amb dni 10 i nom Carme te 5 inscripcions
El soci amb dni 11 i nom Nuria te 5 inscripcions
El soci amb dni 12 i nom Josep te 3 inscripcions
Nombre de socis consultats 3
Una activitat inserida
Rollback i desconnexio realitzats correctament.
edu@artoo:~/facultat/bd/java$