JDBC et objet

Transcription

JDBC et objet
Types de données de SQL3
‰
JDBC et
objet-relationnel
Université de Nice - Sophia Antipolis
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
Version 1.6.4 – 5/11/11
Richard Grin
R. Grin
Le type de collection VARRAY d’Oracle permet
d'avoir des colonnes multivaluées
‰ Ils correspondent en Java à l’interface
java.sql.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
Remarque : cette interface sert aussi pour les
collections « tables imbriquées » d’Oracle
(nested tables)
R. Grin
JDBC et relationnel-objet
page 3
R. Grin
Récupérer les éléments d’un Array
‰
On peut aussi récupérer un tableau Java entier
par la méthode Object getArray() de
Array
R. Grin
JDBC et relationnel-objet
JDBC et relationnel-objet
page 4
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
‰
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()
‰
page 2
Récupérer un Array
Array
‰
JDBC et relationnel-objet
page 5
R. Grin
JDBC et relationnel-objet
page 6
1
Lire des éléments d’un Array
Enregistrer un tableau
String[] data;
// remplit le tableau
. . .
PreparedStatement ps =
conn.prepareStatement(
"Update table1 "
+ "set tableau = ? where num = 5");
ps.setObject(1, data);
R. Grin
JDBC et relationnel-objet
String[] data;
Statement stmt = conn.createStatement();
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]);
}
}
page 7
R. Grin
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é :
R. Grin
JDBC et relationnel-objet
page 9
page 8
Type utilisateur
‰
String[] data;
Statement stmt = conn.createStatement();
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));
}
}
JDBC et relationnel-objet
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
Utilisation des types distinct et
structuré dans la définition d’une table
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))
R. Grin
JDBC et relationnel-objet
page 11
create table emp (
matr matricule constraint pkEmp primary key,
nomE varchar(15),
. . .
dept departement_type)
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
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
3. Indiquer le type structuré qui correspond à la
classe Java
R. Grin
JDBC et relationnel-objet
page 13
R. Grin
Interface SQLData
JDBC et relationnel-objet
page 14
SQLInput et SQLOutput
public interface SQLData {
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
‰
/** 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
R. Grin
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
. . .
JDBC et relationnel-objet
page 16
Implémenter SQLData (2)
Implémenter SQLData (1)
R. Grin
JDBC et relationnel-objet
page 17
// 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();
L’ordre de lecture
lieu = flot.readString();
(et d’écriture)
}
doit être celui donné
dans la définition
du type structuré
R. Grin
JDBC et relationnel-objet
page 18
3
Correspondance entre les classes
Java et les types structurés
Implémenter SQLData (3)
public void writeSQL(SQLOutput flot)
throws SQLException {
flot.writeInt(numDept);
flot.writeString(nomDept);
flot.writeString(lieu);
}
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 :
‰
public String getSQLTypeName() {
return nomTypeSQL ;
}
Map map = conn.getTypeMap();
map.put("toto.depart_type", p1.Dept.class);
}
R. Grin
JDBC et relationnel-objet
page 19
R. Grin
Il est alors simple de lire et d’écrire des valeurs du
type structuré :
Statement stmt = conn.createStatement();
ResultSet rset = stmt.executeQuery(
"SELECT * FROM EMP");
while (rset.next()) {
Dept dept = (Dept)rset.getObject("DEPT");
System.out.println("Lieu du dept : "
+ dept.getLieu());
}
R. Grin
JDBC et relationnel-objet
page 21
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
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
‰
JDBC et relationnel-objet
JDBC et relationnel-objet
page 22
Lecture sans utiliser la Map
Sans utilisation de la Map
R. Grin
page 20
Écriture d’un type structuré
Lecture d’un type structuré
‰
JDBC et relationnel-objet
page 23
Statement stmt = conn.createStatement();
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 24
4
Références en SQL 3
Nouveau type de table 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
‰
R. Grin
JDBC et relationnel-objet
page 25
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
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. Grin
JDBC et relationnel-objet
page 27
R. Grin
JDBC et relationnel-objet
page 29
page 26
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
Récupération d’une référence
java.sql.Ref refDept;
Statement stmt = conn.createStatement();
ResultSet rset1 = stmt.executeQuery(
"SELECT dept from emp " +
"where matricule = 105");
if (rset1.next()) {
refDept = rset1.getRef("dept");
if (! rset1.wasNull()) {
...
JDBC et relationnel-objet
JDBC et relationnel-objet
page 28
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

Documents pareils