IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JDBC Java Discussion :

Récupérer un TYPE Oracle via JDBC.


Sujet :

JDBC Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France, Yvelines (Île de France)

    Informations forums :
    Inscription : Juin 2009
    Messages : 61
    Par défaut Récupérer un TYPE Oracle via JDBC.
    Bonjour, je crée en Java une simple application qui permet de traiter des DVD. J'ai rencontré un problème lors de la récupération d'un UDT complexe via jdbc. Les recherches sur internet ont été infructueuses et je voulais savoir si vous pouviez m'aider.

    La base de données contient un ensemble de films. Les films ont un réalisateur, un ou plusieurs acteurs, un ou plusieurs genres (fantastique, action, horreur...).

    Je me suis dis pour faire simple, je vais créer un TYPE FILM_TY, qui aura la même structure que ma classe java : Film. Comme cela, lorsque je cliquerais sur un des films se trouvant dans une JList, j'appellerai la fonction que j'ai créé getFilm() sous Oracle par procédure stocké et un mappage me permettra de récupérer directement l'objet sous java.

    Voici les différents UDT créés sur SQL Developer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    CREATE OR REPLACE TYPE PERSONNE AS OBJECT(
    prenom VARCHAR2(50),
    nom VARCHAR2(50)
    );
    
    CREATE OR REPLACE TYPE PERSONNE_ARRAY AS VARRAY(10) OF PERSONNE;
    
    CREATE OR REPLACE TYPE GENRE_ARRAY AS VARRAY(10) OF VARCHAR2(50);
    
    CREATE OR REPLACE TYPE FILM_TY AS OBJECT (
    numFilm INTEGER,
    titreFilm VARCHAR2(50),
    originalFilm VARCHAR2(50),
    langueFilm VARCHAR2(30),
    dateFilm INTEGER, 
    zoneFilm INTEGER,
    emprunteur VARCHAR2(50),
    numRealisateur INTEGER,
    realisateur personne,
    acteurs personne_array,
    genres genre_array,
    
    MEMBER FUNCTION getRealisateur RETURN PERSONNE,
    MEMBER FUNCTION getActeurs RETURN PERSONNE_ARRAY,
    MEMBER FUNCTION getGenres RETURN GENRE_ARRAY
    );
    La fonction getFilm(titre VARCHAR2) qui renvoie un Film_ty en piochant les informations dans la base donnée à partir du titre du film, marche correctement (test PL/SQL).

    Maintenant, la chose que je n'avais jamais fait avant, c'était récupéré des objets oracle(types) via jdbc. J'ai donc suivit le pauvre mais néanmoins intéressant tuto sur la relation entre UDT et Objet Java.

    Cependant, à la ligne où je fais getObject("Film_ty"), j'ai l'erreur suivante :
    java.sql.SQLException: opération interdite: Ordinal binding and Named binding cannot be combined!
    Voici quelques parties de mon code java :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    // LA CLASSE PERSONNE
    public class Personne implements SQLData {
    	private String nom;
    	private String prenom;
    	private String typeSql; 
    	
    	public Personne(String p, String n)
    	{
    		setNom(n);
    		setPrenom(p);
    	}
    	
    	public String getSQLTypeName() throws SQLException {
    		return typeSql;
    	}
    
    	public void readSQL(SQLInput stream, String typeName) throws SQLException {
    		typeSql = typeName;
    		prenom = stream.readString();
    	    nom = stream.readString();  
    	}
    
    	public void writeSQL(SQLOutput stream) throws SQLException {
    		stream.writeString(prenom);
    	    stream.writeString(nom);
    	}
    }
    
    // LA CLASSE FILM
    public class Film implements SQLData, Comparable<Film> {
    	private int numFilm;
    	private int numRealisateur;
    	private String nomFilm;
    	private String nomOriginal;
    	private int dateSortie;
    	private String langue;
    	private String emprunteur;
    	private int zoneFilm;
    	private Personne realisateur;
    	private String genres[] = new String[10];
    	private Personne acteurs[] = new Personne[10];
    	
    	private String typeSql; 
    	private CallableStatement cst;
    	private Connection co;
    	
    
    	public Film(String nom)
    	{
    		nomFilm = nom;
    		numFilm = 0;
    		co = ConnectionBase.getConnection();
    	}
    	
    	public String getSQLTypeName() throws SQLException {
    		return typeSql;
    	}
    
    
    	public void readSQL(SQLInput stream, String typeName) throws SQLException {
    		Array a, g;
    		typeSql = typeName;
    		setNumFilm(stream.readInt());
    		nomFilm = stream.readString();
    		nomOriginal = stream.readString();
    		langue = stream.readString();
    		dateSortie = stream.readInt();
    		zoneFilm = stream.readInt();
    		emprunteur = stream.readString();
    		setNumRealisateur(stream.readInt());
    		realisateur = (Personne)stream.readObject();
    		a = stream.readArray();
    		g = stream.readArray();
    		acteurs = (Personne[])a.getArray();
    		genres = (String[])g.getArray();
    	}
    
    
    	public void writeSQL(SQLOutput stream) throws SQLException {
    		stream.writeInt(numFilm);
    // suite de stream.write...
    		stream.writeObject(realisateur);
    	}
    Et la fameuse fonction qui ne fonctionne pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public Film getFilm()
    {
    	Film f = null;
    	if(numFilm == 0) // si le film n'a pas été récupéré encore
    	{
    		if(co != null) // si la connexion à la base est correct
    		{
    			Map<String, Class<?>> map;
    			try {		
    				map = co.getTypeMap();
    				map.put("Schema.FILM_TY", Class.forName("Modeles.Film"));
    				map.put("Schema.PERSONNE", Class.forName("Modeles.Personne"));
     
    				cst = co.prepareCall("{? = call getFilm(?)}");
    				cst.registerOutParameter(1, java.sql.Types.STRUCT, "FILM_TY");					
    				cst.setString(2, nomFilm);
    				cst.execute();
    				f = (Film)cst.getObject("FILM_TY"); // ICI, l'exception est lancée
     
    				cst.close();
    			} catch (SQLException e) {
    				System.out.println(e);
    			} catch (ClassNotFoundException e) {
    				System.out.println(e);
    			}
    		}
    	}
    	return f;
    }
    La classe que j'essaye de récupérer est assez complexe, elle contient d'autre TYPE (personne) et des tableaux (VARRAY) d'où peut-être, la difficulté à "caster" l'UDT en objet java.

    Pouvez vous me dire où se trouve le problème et comment le corriger svp ?

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    111
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 111
    Par défaut
    A la place de ce type d'appel de fonction :
    cst = co.prepareCall("{? = call getFilm(?)}");
    Tu peux utiliser un PreparedStatement avec la requête suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select getFilm(?) from dual
    Et pour récupérer ton film il te faudra faire un getObject() sur ton resultset :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Film film= (Film)resultset.getObject(1);

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France, Yvelines (Île de France)

    Informations forums :
    Inscription : Juin 2009
    Messages : 61
    Par défaut
    Ça ne marche pas non plus. Je n'avais encore jamais utilisé de preparedStatement, donc la manière dont c'est écrit peut être fausse.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    if(co != null)
    {
    	Map<String, Class<?>> map;
    	try {		
    		ResultSet res;
    		map = co.getTypeMap();
    		map.put("Schema.FILM_TY", Class.forName("Modeles.Film"));
    		map.put("Schema.PERSONNE", Class.forName("Modeles.Personne"));
     
    		PreparedStatement cst = co.prepareCall("select getFilm(?) from dual");				
     
    		cst.setString(1, nomFilm);
    		res = cst.executeQuery();
    		res.next();
    		f = (Film)res.getObject(1);
    		cst.close();
    	} catch (SQLException e) {
    		System.out.println(e);
    	} catch (ClassNotFoundException e) {
    		System.out.println(e);
    	}
    }
    Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: oracle.sql.STRUCT cannot be cast to Modeles.Film

  4. #4
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Non, c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    PreparedStatement pstmt = co.prepareStatement("la requête SQL");
    pas co.prepareCall
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France, Yvelines (Île de France)

    Informations forums :
    Inscription : Juin 2009
    Messages : 61
    Par défaut
    Ok, j'ai modifié, mais j'ai la même erreur.
    Je ne pense pas que l'erreur vienne de comment j'essaye de récupérer les données (instruction paramétrée ou procédure stockée...), ça doit surement venir de plus loin, c'est à dire de comment je mets en relation l'objet java avec le type oracle. Néanmoins, je ne sais toujours pas où je fais faux bon...
    Enfin je dis ça, je ne suis pas sur. Je crois qu'il est possible de récupérer le type par procédure stockée.

Discussions similaires

  1. Réponses: 3
    Dernier message: 25/08/2011, 14h23
  2. Se connecter à informix depuis une base Oracle via JDBC
    Par aznkd dans le forum Connexions aux bases de données
    Réponses: 4
    Dernier message: 20/04/2008, 23h18
  3. [Oracle] Problème d'insertion de ligne via JDBC
    Par Invité dans le forum JDBC
    Réponses: 3
    Dernier message: 17/07/2007, 12h21
  4. [Oracle 10g XE]Création d'une bd via jdbc
    Par slim dans le forum Administration
    Réponses: 3
    Dernier message: 19/04/2007, 08h46
  5. Réponses: 4
    Dernier message: 14/06/2006, 11h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo