Construire un JTree a partir d'une requête SQL

:hello: Bonjour à tous !

Je viens solliciter votre aide car après mainte recherche je reste bloqué.

Mon but ?

Créer un JTree en java qui reprendrai la structure de ma base de données.
Ensuite celui-ci me servira à ajouter des champs dans un JTextArea pour élaborer une requête SQL sur ma base Oracle.

Voila un screenshot de Eclipse Birt qui affiche parfaitement ce que je veux :

http://pics.imagup.com/04/1246401376_jtree_bddoracle.jpg

J’ai bien réussi à récupérer la liste des tables via l’objet “DatabaseMetaData” et la méthode “getTables” mais je ne vois pas comment récupérer
la liste des champs et les ajouter à mon JTree.

Merci d’avance.

Tu as pas aussi de la même façon les TableMetaData?

Hmm je n’avais rien trouvé à sujet, mais je suis tombé sur une page intéressante ICI

Merci :wink:


J'ai fait un test rapide avant de partir du boulot avec le lien.

Cela me ramène bien la liste des tables et leurs champs (vérifier avec un System.out.println).

Je test demain pour le JTree.

Encore Merci sans-nom
Edité le 30/06/2009 à 17:58

:hello: Bonjour,

Et bien j’ai tester avec le code du lien et c’est long… très très long.

Du coup je cherche depuis hier une autre méthode et je pense avoir trouver.

Je vous montres le code histoire d’aider ceux qui en ont besoin. N’hésitez pas si vous voyez des soucis :jap:

[spoiler]


import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

import oracle.jdbc.pool.OracleDataSource;


public class Test {
	
	public static void main(String[] args) {
		
		Connection connection = null;
		
		String url = "mon_url";
		String user = "user";
		String pass = "pass";
		
		try {
			
			OracleDataSource ods = new OracleDataSource();
			ods.setURL(url); 
			ods.setUser(user);
			ods.setPassword(pass);
			connection = ods.getConnection();

			DatabaseMetaData dmd = connection.getMetaData(); // Recupération des informations de la BDD
			String[] type = {"TABLE"}; // Je ne souhaite afficher que les TABLES
			ResultSet rset = dmd.getTables(null, user, "%", type);
			
			while(rset.next()) {
				System.out.println(rset.getString("TABLE_NAME")); // Affichage du nom de la Table
				/**
				 * Je fait une requête sur la Table et je ne récupère qu'une Ligne
				 * Le rownum remplace le mot clé LIMIT pour Oracle
				 */
				String query = "Select * from " + rset.getString("TABLE_NAME") + " where rownum < 2";
				Statement stmt = connection.createStatement();
				ResultSet rset2 = stmt.executeQuery(query);
				
				while(rset2.next()) {
					ResultSetMetaData rset3 = rset2.getMetaData(); // Récupération des informations de la requête
					int nbCol = rset3.getColumnCount(); // Je compte le nombre de colonne
					
					for (int i = 1; i <= nbCol; i++) {
						String nomCol = rset3.getColumnName(i);
						String typCol = "(" + rset3.getColumnTypeName(i) + ")";
						System.out.println("\t" + nomCol + typCol);
						
					}
					
				}
				stmt.close();
				rset2.close();				
			}
			rset.close();
			connection.close();
		
		} catch (SQLException sql) {
			sql.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

[/spoiler]

Voila aussi le code pour le JTree :
[spoiler]


	public void tableList() {
		
		Connection conn = null;
		
		String url = "";
		String user = "";
		String pass = "";
		
		racine = new DefaultMutableTreeNode(user);
					
		try {
			
			OracleDataSource ods = new OracleDataSource();
			ods.setURL(url); 
			ods.setUser(user);
			ods.setPassword(pass);
			conn = ods.getConnection();
	    	
			try {
				DatabaseMetaData dbm = conn.getMetaData();
				String[] types = {"TABLE"};
				ResultSet rs = dbm.getTables(null,user,"%",types);
											
				while (rs.next()){
					
					tableTree = new DefaultMutableTreeNode(rs.getString("TABLE_NAME"));
					
					
					String query = "Select * from " + rs.getString("TABLE_NAME") + " where rownum < 2";
					Statement stmt = conn.createStatement();
					ResultSet rset2 = stmt.executeQuery(query);
					
					while(rset2.next()) {
						ResultSetMetaData rset3 = rset2.getMetaData();
						int nbCol = rset3.getColumnCount();
						for (int i = 1; i <= nbCol; i++) {
							String nomCol = rset3.getColumnName(i);
							tableTree.add( new DefaultMutableTreeNode(nomCol));
						}
					}
					rset2.close();
					racine.add(tableTree);							
				}					
				rs.close();
				conn.close();		
			} catch (SQLException sqle) {
				JOptionPane.showMessageDialog(null, sqle.getMessage(), "Erreur SQL", JOptionPane.ERROR_MESSAGE);
			}
			
		} catch (Exception e) {
	    	JOptionPane.showMessageDialog(null, e.getMessage(), "Erreur", JOptionPane.ERROR_MESSAGE);
	    	e.printStackTrace();
	    }
	}

[/spoiler]
Edité le 02/07/2009 à 11:38

Heu… 2 remarques :

  • Quit à faire du code d’exploration de base qui possède une grosse glue vis à vis de la base, pourquoi ne pas passer par des requêtes natives ?

  • Le deuxième code est tout pourri à mélanger interrogation de base et présentation…

C’est à dire ?

Les DatabaseMetadata, etc… ?

En attendant ça fonctionne et comme j’ai pas trouver d’exemple ni de bonne âme apte à m’aider je me suis débrouiller :wink:
Si tu as mieux, je suis prenneur :jap:

Ben en exécutant des requêtes comme si tu interrogeait directement ta base. Surtout que si je ne me trompe pas, il y a une table de description des tables dans Oracle. Ca doit faire un truc du genre :

SELECT column_name FROM user_tab_columns WHERE table_name=?;

sachant que tu a récupéré les noms de table. C’est ni portable ni objet, mais si tu a des problèmes de perfs, là tu saura a moins que c’est un problème de base.

Je ne vais pas représenter toute la théorie du découpage logiciel en couches, mais ta classe d’accès aux données (DAO) ne doit contenir qu’une interrogation de la base et un retour “abstrait”. Ce peut être une grappe d’objets décrivant ta structure du type :

MaBase-(1)—()-Tables-(1)—()-Colonnes

C’est au niveau de la présentation que tu va mapper cette grappe sur ton JTree.

L’intérêt est que tu aura comme ça une classe de présentation réutilisable indépendamment de la base de données (il faudra coder une Dao adaptée) et ta classe d’exploration de la base n’est plus uniquement liée à une présentation que tu pourra réutiliser dans d’autres contextes, ta méthode devenant “getDatabaseDescription()”

Voila voila

:hello: Bonjour !!

Je viens de tester de cette manière et niveau temps c’est kiff kiff. J’y avais penser, d’ailleurs le morceau de code est toujours sur un bout de papier à côté de moi, mais je pensai qu’utiliser la méthode “getMetaData” était plus “propre”. Cela dit, je ne connaissais pas la table “user_tab_columns”, merci :jap:

Je vois bien ce que tu veux dire en ce qui concerne le portage mais pour l’instant je vois mal comment dissocié : Interrogation de la base et Construction du JTree.

L’intérêt de mon projet étant, pour l’instant de disposer d’un outil simple de requêtage sur notre base de données (comme on le fait actuellement sur notre AS400)

Enfin, je vais me pencher sur tout ça, sachant que j’ai commencer le Java il y à 2 mois :stuck_out_tongue:

Merci de ton aide :jap:

Je n’ai jamais eu à faire de l’exploration de base en Java, donc j’admets ne pas m’être trop intéressé au sujet, mais comme je te l’ai dit : utiliser ta getMetaData est plus générique et donc tu pourrait réutiliser ce que tu a codé pour d’autres bases. Le problème dans la conception ici est de bien faire la part entre les bénéfices/déficites de la généricité ou de la spécialisation.

C’est une certaine difficulté… Ok vu la remarque suivante…

Arf… Donc 2 mois d’objet, je vais éviter de parler de patterns de conception, tout ça tout ça…

Bon, note ce que je t’ai dit, et repense y quand tu aura cerné un peu la conception Objet. Évidemment, n’hésite pas à reposer une question.

De rien

J’ai lu le tuto du Site du Zéro concernant les patterns (MVC, etc…), mais c’est encore assez complexe pour moi et comme " j’étudie " du boulot je n’ai pas forcément la concentration nécessaire pour comprendre ce concept.

Autant l’apprentissage du Java en lui même m’a paru simple, autant cette notion est d’un niveau assez supérieur.

Une fois que j’aurai fini mon projet, c’est à dire d’ici peu, j’essayerai de le mettre aux normes.

Oui oui, ce n’est plus boxer dans la même catégorie. Après, Java est simple à prendre en main, mais pas forcément facile à utiliser correctement (la question piège classique : tu est sûr d’avoir compris le principe des Interfaces, hein :wink: ). Si tu n’en a pas déclaré une seule dans ton projet, alors tu a compris la syntaxe de java, mais pas la conception objet. Ce n’est pas une critique mais un repère :wink:

Si tu arrive à mettre la main dessus : www.amazon.fr…