[Java/MSAccess] et les Metadata

Bonjour,
je suis en train d’essayer de récupérer des infos sur une base de donnée MS.Access en java en utilisant le driver jdbcOdbcDriver proposé par java.
Bref, avec MySQL, j’interroge mes metadata avec des fonctions comme getTables(…), getPrimaryKeys(…) ,… pour connaitre les clés primaires et les clés étrangère des tables présentes dans la bdd.

Je dois faire de même avec une base Access. Joie.

J’arrive à récupérer les metadata, mais dès qu’il s’agit de les utiliser, c’est une autre histoire.
Bout de code pour illustrer tout ca :

[code] String[] types = new String[1];
types[0] = “TABLE”;
LinkedList tables = new LinkedList();

		String dbName = "Prout.mdb";
		String dbPath = "D:\\Data\\Access\\";
		String fullConnectionString = "jdbc:odbc:driver={Microsoft Access Driver (*.mdb)};DBQ=" + dbPath + dbName;
		Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		
		Connection con = DriverManager.getConnection(fullConnectionString);
		Statement stmt = con.createStatement();

		// Récupération des metadata
		java.sql.DatabaseMetaData myMetaData = con.getMetaData();

		// Je récupère les noms de toutes les tables de la base 
		res = myMetaData.getTables(con.getCatalog(),null,"%",types);
		while(res.next())
			tables.add(res.getString("TABLE_NAME"));
		
		for (String elem : tables) {
			System.out.println(elem);
			
			// PRIMARY KEYS
			ResultSet primaryKeys = myMetaData.getPrimaryKeys(con.getCatalog(), null, elem);
			
			while (primaryKeys.next())
				System.out.println("\t" + primaryKeys.getString("COLUMN_NAME"));[/code]

Le remplissage de ma LinkedList tables se passe correctement, quand je la parcours et l’affiche, ca me liste les tables présentent dans la base. Le problème survient lors de la récupération des PK. La méthode getPrimaryKeys(con.getCatalog(), null, elem) me lève l’exception :

[quote]DB Acces connection failed !
[Microsoft][Gestionnaire de pilotes ODBC] Le pilote ne prend pas cette fonction en charge
java.sql.SQLException: [Microsoft][Gestionnaire de pilotes ODBC] Le pilote ne prend pas cette fonction en charge
at sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6957)
at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7114)
at sun.jdbc.odbc.JdbcOdbc.SQLPrimaryKeys(JdbcOdbc.java:4916)
at sun.jdbc.odbc.JdbcOdbcDatabaseMetaData.getPrimaryKeys(JdbcOdbcDatabaseMetaData.j
va:2976)[/quote]

D’où ma question : comment fait on pour récupérer ce genre d’infos sur une base Access ?
Parce que évidement, mon problème se répète quand j’essaie de trouver les clés étrangères avec getForeignKeys(…), …

merci.

Apparemment, y aurait la possibilité de récupérer les clés depuis les bases système d’access. Y aurait il un connaisseur ?

Je ne sais pas ce que ça vaut mais :

http://forum.java.sun.com/thread.jspa?thre…ssageID=1792485

Dans les exemples DAO d’access 97 visiblement la seule possibilité c’est de parcourir la liste des index jusqu’à ce que l’on trouve la clé primaire. ll me semble que c’est ce fait le lien en java de ZGoblin.

edit:

Je viens de regarder. S’il existe des bases systèmes sous SQL server qui font ça, il n’y a quasiment rien dans les bases systèmes d’Access concernant ta question. (Pour vérifier dans Access: Outils / Options /Affichage / Objets systèmes).

Bon après, lire une base access d’une application java j’ai du mal à comprendre.

Bien vu ZGoblin! Putain tu me sort une poutre du pied. J’ai pas bien regardé comment le code fonctionnait, mais ça marche c’est ce qui compte. Je juste la dessus depuis hier alors un grand MERCI mec.

tiens, des fleurs : B)

EDIT : phili_b -> Cherche pas, c’est pour mon école…

[quote=« DexterWard, post:5, topic: 46137 »]Bien vu ZGoblin! Putain tu me sort une poutre du pied. J’ai pas bien regardé comment le code fonctionnait, mais ça marche c’est ce qui compte. Je juste la dessus depuis hier alors un grand MERCI mec.

tiens, des fleurs : B)

EDIT : phili_b → Cherche pas, c’est pour mon école…[/quote]

Franchement, faut pas, une simple recherche Google avec les termes odbc jdbc primary key :
http://www.google.fr/search?q=odbc+jdbc+pr…lient=firefox-a

Et tu prend le premier résultat. B)

PS: moi non plus j’ai rien compris au code :smiley:

Bon ben, en fait je crois que je me suis emballé, c’est cool, je chope les clés primaires, mais les clés étrangère c’est autre chose…

Pour google, j’ai cherché sur getPrimaryKey access, jdbc odbc, … suis jamais tombé la dessus. Bref, je vais relancer une recherche en utilisant “odbc jdbc foreign kex” ce coup ci.

croise les doigts

les clés étrangères ??!! J’ai un doute sur ce que tu recherches.
Il y a deux choses qui forment ce que tu appelles une clé étrangère[ul]
[li]d’une part les contraintes d’intégrités (dans la table système MSysRelationships d’Access). Et là cela n’a rien à voir avec des index. C’est la relation entre une table maitre et une table fille (1-n)[/li][li]d’autre part les index liés à une contrainte d’intégrité. Dans la table maitre ça sera la clé primaire ou tout au moins une clé unique. Tandis que dans la table fille ça sera un index “tout bête”. Et rien n’indiquera qu’un index sert à une contrainte d’intégrité sauf à faire le rapprochement par le nom de la colonne ou la similitude entre le nom de l’index et le nom de la contrainte.[/li][/ul]edit: Tout ce que je viens de dire est valable dans tout les SGBDR (excepté la table MSysRelationships ).

Par contre voici un extrait d’un exemple des propriétés en DAO sous Access. Là ça devient une cuisine spécifique à Access. N’empêche que ça liste les contraintes d’intégrités et non les index liés à celle-ci. Il y a sûrement des méthodes java qui font appel à ces méthodes access.
[codebox]Sub ForeignNameX()

Dim dbsNorthwind As Database
Dim relLoop As Relation

Set dbsNorthwind = OpenDatabase("Comptoir.mdb")

Debug.Print "Relation"
Debug.Print "                    Table - Champ"
Debug.Print "    Primaire (Un)   ";
Debug.Print ".Table - .Champs (0).Name"
Debug.Print "    Externe (Plusieurs)  ";
Debug.Print ".ForeignTable - .Fields(0).ForeignName"

' Enumère la collection Relations de la base de
' données Comptoir pour créer un état des valeurs

’ des propriétés attachées aux objets Relation et à
’ leurs objets Field.
For Each relLoop In dbsNorthwind.Relations
With relLoop
Debug.Print
Debug.Print .Name & " Relation"
Debug.Print " Table - Champ"
Debug.Print " Primaire (Un) ";
Debug.Print .Table & " - " & .Fields(0).Name
Debug.Print " Externe (Plusieurs) ";
Debug.Print .ForeignTable & " - " & _
.Fields(0).ForeignName

End With
Next relLoop

dbsNorthwind.Close

End Sub[/codebox]
Pour info les contraintes sous Access 97 se définissent dans le menu Outils/Relations ou en VBA mais pas avec des ALTER contrairement aux “vrais” SGBDR": “Le moteur de base de données Microsoft Jet ne gère pas l’utilisation de CONSTRAINT ou des instructions de langage de définition de données (DDL) avec les bases de données non-Microsoft Jet. Utilisez plutôt les méthodesCreate des objets d’accès aux données (DAO, Data Access Objects).” En tout cas sous 97.

Tu soulèves un point intéressant ^^

Je vais donc expliquer mon problème plus en profondeur. Pour faire simple, je dois réussir à trouver les liens entre les tables d’une bdd Access (entre autre) pour pouvoir effectuer des jointures par exemple. Le but étant de convertir de l’algèbre relationnelle en SQL.
Prenons l’exemple de la jointure (naturelle) en AR entre les relations R1 et R2 ce qui nous donne :

R1 JOIN R2

avec R1(#att1, att2, att3) et R2(#att2, att4, att5) le # représentant la clé primaire

Je suis dans un cas 1-n où att1 et la clé primaire de R1, et att2 celle de R2. Mais att2 est aussi une clé étrangère de R1 (provenant de R2)

Si je veux effectuer l’équivalent de la requête AR en SQL, je dois trouver sur quel(s) attribut(s) effectuer ma jointure en SQL. Et le seul moyen que je vois est de récupérer les clés primaires ainsi que les clés étrangères pour créer ma jointure dans la clause WHERE de la requête SQL pour obtenir une requête du genre :

SELECT * FROM R1, R2
WHERE R1.att1 = R2.att2

Alors, je vois pas comment je pourrait m’y prendre autrement qu’en récupérant les clés primaires (et étrangères) de chaque table.

Vous m’avez compris ? Je bloque la dessus depuis plusieurs jours, je vais devenir chèvre…

[quote=“DexterWard, post:9, topic: 46137”]Et le seul moyen que je vois est de récupérer les clés primaires ainsi que les clés étrangères pour créer ma jointure dans la clause WHERE
[…]
Alors, je vois pas comment je pourrait m’y prendre autrement qu’en récupérant les clés primaires (et étrangères) de chaque table.[/quote]
Le souci, surtout dans les bases access, c’est que beaucoup de personnes oublient ou ne veulent pas créer de contraintes d’intégrités alors que c’est indispensable pour la cohérence des données. Donc ta solution de chercher les clés primaires et les index des clés étrangères serait un pis-aller nécessaire dans un cadre professionnel. Mais ton projet se situe dans un cadre scolaire donc en théorie avec une implémentation suivant les règles de l’art. Et les règles de l’art c’est de créer autant de contrainte d’intégrité que de liens de cohérence de données nécessaires et donc de chercher uniquement les contraintes d’intégrités et pas les index.

Après effectivement il peut exister des jointures telles que si 3 tables soient jointes entre elles par des contraintes, on peut faire une jointure de la première table vers la 3é table. Mais ce n’est pas les index qui vont t’aider en théorie mais la (notion de math dont j’ai oublié le nom (*) ):

si j’ai les contraintes Table1.colA=Table2.colA et table2.colA=Table3.ColA alors on peut déduire que Table1.colA=Table3.colA est possible.

Et c’est seulement une fois que tu as épuisé tout cela que tu pars vers l’homonymie des noms des index ou des noms de colonne. Tout en sachant que cette dernière règle ne sera jamais que conjecture et pas gravée dans le marbre comme les contraintes d’intégrité.

(*)=Autant je pense maitriser la partie modélisation des SGBD, autant j’ai toujours eu beaucoup de mal avec le vocabulaire mathématiques. Dès qu’il y a des notations mathématiques j’ai du mal à suivre surtout quand c’est théorique. C’est seulement maintenant que je connais bien la modélisation des SGBD que je comprends l’intérêt de l’algèbre relationnel ou les espaces vectorielles pour d’autres domaines.

Je vois ce que tu veux dire, et autant dire que c’est la merde.
Je vais essayer de voir s’il est possible de tout simplement préciser sur quel champs portent la jointure dans la requête AR plutôt que de continuer a m’enliser avec tout ca.

Sinon, le mot que tu cherche c’est pas transitive ? (ca remonte un peu la dernière fois que j’ai vu ces notions sur les ensembles)