Types de données de SQL3 JDBC et objet-relationnel Université de Nice - Sophia Antipolis Version 1.6.4 5/11/11 Richard Grin JDBC supporte les types suivants de SQL3 qui sont des ouvertures vers le relationnelobjet : n ARRAY n types structurés définis par l utilisateur n références vers des instances de types structurés R. Grin JDBC et relationnel-objet page 2 Array Le type de collection VARRAY d Oracle permet d'avoir des colonnes multivaluées Ils correspondent en Java à l interface java.sql.array Remarque : cette interface sert aussi pour les collections «tables imbriquées» d Oracle (nested tables) Récupérer un Array Un Array enregistré dans une base de données peut être récupéré en Java sous la forme d une instance de la classe Array par les méthodes suivantes de ResultSet n Array getarray(string nomcolonne) n Array getarray(int numcolonne) On récupère ainsi une référence qui peut servir à obtenir les valeurs de l array R. Grin JDBC et relationnel-objet page 3 R. Grin JDBC et relationnel-objet page 4 Récupérer les éléments d un Array On peut ensuite récupérer dans un tableau Java des éléments d un Array (pas nécessairement tous) par les méthodes de l interface Array Object getarray(long debut, int longueur) ou en utilisant un ResultSet par ResultSet getresultset() On peut aussi récupérer un tableau Java entier par la méthode Object getarray() de Array Enregistrer un Array void setarray(int i, Array x) de PreparedStatement permet d enregistrer un Array ResultSet contient la méthode updatearray pour les resultsets modifiables PreparedStatement permet aussi d enregistrer un tableau Java sous forme de Array avec la méthode setobject R. Grin JDBC et relationnel-objet page 5 R. Grin JDBC et relationnel-objet page 6 1
Enregistrer un tableau String[] data; // remplit le tableau PreparedStatement ps = conn.preparestatement( "Update table1 " + "set tableau =? where num = 5"); ps.setobject(1, data); Lire des éléments d un Array String[] data; ResultSet rset = stmt.executequery( "select * from table1 where num = 5"); if (rset.next()) { Array array = rset.getarray("tableau"); // ne récupère que les éléments 5 et 6 du tableau data = (String[])array.getArray(4, 2); for (int i = 0; i < data.length; i++) { System.out.println(data[i]); R. Grin JDBC et relationnel-objet page 7 R. Grin JDBC et relationnel-objet page 8 Lire des éléments d un Array On peut aussi utiliser un ResultSet pour lire les éléments d un tableau déjà récupéré : String[] data; ResultSet rset = stmt.executequery("select "); if (rset.next()) { Array array = rset.getarray("tableau"); // ne récupère que les éléments 5 et 6 du tableau ResultSet rsarray = array.getresultset(4, 2); while (rsarray.next()) { System.out.println(rsArray.getString(1)); R. Grin JDBC et relationnel-objet page 9 Type utilisateur SQL 3 a introduit 2 formes de nouveaux types créés par l utilisateur : n type «distinct», construit simplement à partir d un type de base n type «structuré», plus complexe, construit sur le modèle d une classe Java R. Grin JDBC et relationnel-objet page 10 Type structuré Ces types rapprochent les SGBD relationnels du monde objet Ils sont créés par la commande SQL 3 «create type» : create type departement_type as object ( numdept integer, nomdept varchar(15), lieu varchar(20)) Utilisation des types distinct et structuré dans la définition d une table create table emp ( matr matricule constraint pkemp primary key, nome varchar(15), dept departement_type) R. Grin JDBC et relationnel-objet page 11 R. Grin JDBC et relationnel-objet page 12 2
Utilisation des types structurés pour la persistance des classes Java Pour faciliter la persistance des classes Java 1. Créer un type structuré SQL de même structure que la classe 2. La classe Java doit implémenter l interface java.sql.sqldata 3. Indiquer le type structuré qui correspond à la classe Java Utilisation des types structurés pour la persistance des classes Java La lecture et l écriture dans une base de données des données d une instance de la classe Java s effectue alors en un seul appel de méthode getobject ou setobject R. Grin JDBC et relationnel-objet page 13 R. Grin JDBC et relationnel-objet page 14 Interface SQLData public interface SQLData { /** Lire une instance de la classe à partir * à partir des données de la base. */ void readsql(sqlinput stream, String typename) throws SQLException; /** Enregistre une instance de la classe * dans la base de données. */ void writesql(sqloutput stream) throws SQL Exception; String getsqltypename() throws SQLException; R. Grin JDBC et relationnel-objet page 15 SQLInput et SQLOutput Flots qui contiennent des valeurs constituant une instance d un type structuré (ou distinct) SQL Ils sont utilisés par le driver JDBC et le développeur ne les manipulent pas directement R. Grin JDBC et relationnel-objet page 16 Implémenter SQLData (1) public class Dept implements SQLData { private int numdept; private String nomdept, lieu; // Type SQL qui correspond à la classe Dept private String nomtypesql; // Constructeurs et autres méthodes de Dept R. Grin JDBC et relationnel-objet page 17 Implémenter SQLData (2) // Les 3 méthodes de l'interface SQLData public void readsql(sqlinput flot, String type) throws SQLException { nomtypesql = type; numdept = flot.readint(); nomdept = flot.readstring(); lieu = flot.readstring(); L ordre de lecture (et d écriture) doit être celui donné dans la définition du type structuré R. Grin JDBC et relationnel-objet page 18 3
Implémenter SQLData (3) public void writesql(sqloutput flot) throws SQLException { flot.writeint(numdept); flot.writestring(nomdept); flot.writestring(lieu); public String getsqltypename() { return nomtypesql ; Correspondance entre les classes Java et les types structurés Pour faciliter l enregistrement dans la base des données d un type structuré, il faut indiquer le nom (complet, avec le paquetage) de la classe Java qui correspond à ce type On l indique dans une Map utilisée en interne par la connexion : Map map = conn.gettypemap(); map.put("toto.depart_type", p1.dept.class); R. Grin JDBC et relationnel-objet page 19 R. Grin JDBC et relationnel-objet page 20 Lecture d un type structuré Il est alors simple de lire et d écrire des valeurs du type structuré : ResultSet rset = stmt.executequery( "SELECT * FROM EMP"); while (rset.next()) { Dept dept = (Dept)rset.getObject("DEPT"); System.out.println("Lieu du dept : " + dept.getlieu()); Écriture d un type structuré Dept dept = new Dept( ); // Insertion d un nouvel employé PreparedStatement ps = conn.createstatement( "INSERT INTO EMP" + "(matricule,, dept)" + " VALUES (?,,?)"); ps.setint(1, matricule); // Une seule instruction pour le département ps.setobject(8, dept); R. Grin JDBC et relationnel-objet page 21 R. Grin JDBC et relationnel-objet page 22 Sans utilisation de la Map On peut aussi lire une valeur d'un type structuré sans devoir implémenter l interface SQLData ni utiliser la Map qui fait la correspondance entre les classes Java et les types structurés Dans ce cas, on doit lire colonne par colonne en utilisant l interface java.sql.struct Lecture sans utiliser la Map ResultSet rset = stmt.executequery("select * FROM emp"); while (rset.next()) { Struct struct = (Struct)rset.getObject("DEPT"); Object[] valeurs = struct.getattributes(); System.out.println("Lieu du dept : " + valeurs[2]); 3 ème champ R. Grin JDBC et relationnel-objet page 23 R. Grin JDBC et relationnel-objet page 24 4
Références en SQL 3 Le processus de normalisation conduit à éclater les données en plusieurs tables Lorsque l on veut retrouver des informations, on doit alors souvent effectuer des jointures, par exemple pour savoir dans quelle ville les employés travaillent En SQL3 on peut le faire sans que cela ne nécessite de jointure En effet, SQL3 permet de manipuler les références à une information Nouveau type de table SQL 3 Si on veut pouvoir référencer les lignes d'une table T dans une autre table, il faut créer cette table T à partir d'un type structuré Par exemple, à partir du type structuré dept_type, on peut créer la table dept : create table dept of departement_type ( constraint pk_dept primary key dept) R. Grin JDBC et relationnel-objet page 25 R. Grin JDBC et relationnel-objet page 26 Utilisation des références dans la définition d une table create table emp ( matr matricule constraint pkemp primary key, nome varchar(15), dept ref departement_type ) Récupération d une référence On peut récupérer une référence grâce à la méthode getref Si on a une référence, il est possible de l utiliser pour interroger une table qui contient une référence du même type en utilisant setref R. Grin JDBC et relationnel-objet page 27 R. Grin JDBC et relationnel-objet page 28 Récupération d une référence java.sql.ref refdept; ResultSet rset1 = stmt.executequery( "SELECT dept from emp " + "where matricule = 105"); if (rset1.next()) { refdept = rset1.getref("dept"); if (! rset1.wasnull()) {... R. Grin JDBC et relationnel-objet page 29 Utilisation d une référence java.sql.ref refdept;... // Récupère une valeur pour refdept PreparedStatement ps = conn.preparestatement( "SELECT * FROM emp" + " WHERE REF(dept) =?"); ps.setref(1, refdept); ResultSet rset2 = ps.executequery(); while (rset2.next()) { System.out.println(rset2.getString("nom") R. Grin JDBC et relationnel-objet page 30 5
Utilisation d une référence (2) Si on a une référence, le moyen le plus simple pour récupérer l objet référencé est d utiliser la méthode getobject() de Ref R. Grin JDBC et relationnel-objet page 31 deref Il est souvent plus simple d utiliser une requête SQL modifiée pour travailler directement avec l objet référencé Rappel : n deref(référence) permet d obtenir un objet dont on a la référence n La notation pointée (ou la variante syntaxique «->» selon les SGBD) permet de récupérer facilement les valeurs d un objet pointé : dept.lieu R. Grin JDBC et relationnel-objet page 32 Exemple d utilisation d une référence ResultSet rset = stmt.executequery("select dept FROM employe"); while (rset.next()) { Ref refdept = rset.getref("dept"); if(refdept!= null) { Struct struct = (Struct)refDept.getObject(); Object[] val = struct3.getattributes(); String lieudept = (String)val[2];... R. Grin JDBC et relationnel-objet page 33 6