Zi Youltimayte Torque gaïde !
DevFrançaisTutorials
1 Introduction
URL : http://db.apache.org/torque/ et http://db.apache.org/torque-32/
Licence : Apache Software License, Version 1.1
1.1 A quoi ça sert ?
Torque est juste un outils qui permet de générer pour toi des objets java avec tout le mécanisme qui te permettra d’accéder à une base de donnée, même principe qu’Hibernate donc.
1.2 Comment ça marche ?
Il se branche sur le pool de ton serveur d’appli (Tomcat, Weblogic, JBoss…) ou sinon il peut te fournir un pool à lui basé sur commons-dbcp package configurable avec le SharedPoolDataSourceFactory.
Pour la génération automatique des DAO il est capable de prendre en compte les particularités de certaine base (mysql, postgres, oracle, hypersonic, sybase…) pour créer le code en conséquence.
1.3 Est-ce-que ça marche ?
Oui… question suivante ?
Torque 3.2 est sortit le 8 décembre 2005… La maturité du produit est très bonne. Les listes de diffusions sont active (developpeurs et utilisateurs : plus de 100 messages mensuels chacune).
Pour les perfs y à pas de soucis même si je n’ai jamais lancé de bench pour le comparer à d’autre mais ça ne saurait tarder.
2 Comment générer les DAO
2.1 Notre table de démo
Pour tous les exemples suivant, nous allons partir d’une base simplifiée de gestion de bouteilles de vins comme celle-ci.
J’ai pas le temps de faire des beaux tableaux qui prennent de la place…donc :
– En gras : nom de la table
– Après le = les noms de colonnes
– Un + pour dire que c’est un index auto-incrémenté qui fait office de clef primaire
– Des * pour dire que la clef primaire est composé de la ou des colonnes qui ont l’étoile.
1 2 3 4 5 |
<strong>Bouteilles</strong> = id+, nom, annee, quantite, type, format, recoltant <strong>Recoltants</strong> = id+, nom, prenom, tel, courriel, commentaire <strong>Commentaires</strong> = id+, bouteille, date, commentaire <strong>Format</strong> = nom*, contenance <strong>Types</strong> = description* |
A partir de là (euh pendant que j’y suis, je ne veux aucune remarque sur, pourquoi t’as pas mis un index là ? pourquoi la clef primaire de truc elle est pas chose? tu pourrais rajouter tel ou tel champs etc… Je m’en tape, mon but ici n’est pas de faire l’appli de gestion de cave au grand complet !) on va juste créer ce qu’il faut pour travailler avec tout ça.
2.2 Comment faire
Si l’on suit le tutoriel, il faut suivre les étapes suivantes :
1- Créer un XML qui représente le schémas de nos tables
2. Configurer un autre properties pour que torque sache où générer nos classes, dans quel package, pour quelle base…
3. Invoquer torque (via Ant) pour qu’il créé les tables en base et génère aussi vos objets Java.
4. Coder pour que tout fonctionne.
5. Configurer le torque.properties pour que les classes que torque générera puissent communiquer avec la base
2.3 Comment on peut aussi faire
Il est possible que vous souhaitiez :
– soit utiliser une table existante
– soit écrire vous même le SQL de création des tables plutôt que d’écrire le schéma XML pour ensuite tout extraire.
Bon bien dans ce cas c’est pareil, il faut garder les étapes 1, 3 , 4, et 5 qui sont obligatoires et changer l’étape 2 par : demander à Torque d’automatiquement récupérer le schéma de la base et de générer lui même son schéma XML 😉 c’est plus simple comme ça d’ailleurs. Si toutefois vous vouliez quand même faire le schéma XML (J’ai rien contre mais bon) tu peut aller voir là : http://db.apache.org/torque-32/generator/schema-reference.html
Nous on va faire le SQL d’un côté, et la génération des sources de l’autre pour notre exemple.
2.3.1 Le SQL pour créer nos table
Si ça n’est pas déjà fait on va commencer par créer nos tables.
Voilà on créé notre base que l’on va appeler : macave : create database MACAVE; Et on créé les tables (débrouillez-vous vous êtes grand). Le SQL pour générer les tables :
drop table if exists BOUTEILLES; drop table if exists RECOLTANT; drop table if exists COMMENTAIRES; drop table if exists FORMAT; drop table if exists TYPES; create table BOUTEILLES ( ID INT NOT NULL AUTO_INCREMENT, NOM VARCHAR(100) NOT NULL, ANNEE INT(4) NOT NULL, QUANTITE INT NOT NULL DEFAULT 0, TYPE VARCHAR(30) NOT NULL, FORMAT VARCHAR(30), RECOLTANT INT NOT NULL, PRIMARY KEY (ID) ); create table RECOLTANTS ( ID INT NOT NULL AUTO_INCREMENT, NOM VARCHAR(100) NOT NULL, PRENOM VARCHAR(4), TEL VARCHAR(20), COURRIEL VARCHAR(255), COMMENTAIRE VARCHAR(255), PRIMARY KEY (ID) ); create table COMMENTAIRES ( ID INT NOT NULL AUTO_INCREMENT, IDBOUTEILLE INT NOT NULL, DATE DATE, COMMENTAIRE VARCHAR(255), PRIMARY KEY (ID) ); create table FORMAT ( NOM VARCHAR(30) NOT NULL, CONTENANCE VARCHAR(8) NOT NULL, PRIMARY KEY (NOM) ); create table TYPES ( DESCRIPTION VARCHAR(30) NOT NULL, PRIMARY KEY (DESCRIPTION) );
Donc les tables sont créées on peu commencer.
Je suis partit sur un script pour MYSQL, vous adaptez pour votre base.
Les AUTO-INCREMENT sont en MySQL ce que les SEQUENCE sont à ORACLE…
2.3.2 Configuration et génération des classes
On commence par configurer le properties qui va dire à Torque ou aller chercher nos infos de table pour extraire nos objets.
Juste : je considère que vous êtes sous Linux, pour windowz débrouillez-vous ! C’est pas loin d’être pareil et je pense que vous arriverez sans mal à déplacer un fichier, renommer, copier, éditer et tout ça 😉 Pour ce qui est des connecteurs JDBC dans votre classpath, on n’en parle pas hein ! Juste ne pas les oublier et de mettre les bons dans le répertoire lib du générateur de Torque…
Bon donc on se place dans le répertoire de torque-gen-3.1 et on change le build.properties pour mettre nos besoins. On sauvegarde l’ancien build.properties :
[ledruide@neptune]# cd /home/ledruide/outils/dev/torque-gen-3.1/ [ledruide@neptune]# cp build.properties buil.properties_old
Maintenant on va éditer le build.properties. Le plus simple est d’écraser le contenu de l’ancien et de partir de celui-là en changeant ce qui est en gras.
[ledruide@neptune]# vi build.properties
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 |
# le nom du project (autant mettre la même chose que le nom de la table) torque.project=<strong>macave</strong> # le type de base que l'on va utiliser torque.database=<strong>mysql</strong> # le package de destination pour vos sources torque.targetPackage=<strong>org.ledruide.cave.dao</strong> # Ici c'est le répertoire où les sources vont être créées # je ne met pas mon répertoire réel des sources pour ne pas écraser # ce que je possède déjà : torque.home=<strong>/home/ledruide/cave/DAO_temp</strong> # Des répertoires que torque va créer pour bien ranger tout ça # rien besoin de changer torque.output.dir=${torque.home}/src torque.schema.dir=${torque.home}/schema torque.doc.dir=${torque.home}/doc torque.java.dir=${torque.output.dir}/java torque.javadoc.dir=${torque.output.dir}/javadoc torque.ojb.dir=${torque.output.dir}/ojb # ici c'est le répertoire de templates de torque, on s'en tape un peu ;) torque.templatePath=<strong>/home/ledruide/outils/dev/torque-gen-3.1/templates</strong> ######################################################################### ### BASE LOCALHOST # Ok là il faut rentrer votre config # oui c'est très redondant mais bon c'est pas compliqué ! torque.database.createUrl=<strong>jdbc:mysql://localhost:3306/mysql</strong> torque.database.buildUrl=<strong>jdbc:mysql://localhost:3306/macave</strong> torque.database.url=<strong>jdbc:mysql://localhost:3306/macave</strong> torque.database.driver=<strong>org.gjt.mm.mysql.Driver</strong> torque.database.user=<strong>root</strong> torque.database.password=<strong>skol_offensru</strong> torque.database.host=<strong>localhost</strong> torque.database.schema=<strong>MACAVE</strong> torque.database.name=<strong>macave</strong> torque.database.manualCreation=false torque.sameJavaName = false # des paramêtres pour la création des sources # il y en a d'autre le mieux est d'aller voir le manuel de référence torque.addGetByNameMethod = true torque.addIntakeRetrievable = false torque.addSaveMethod = true torque.addTimeStamp = true # Ici CV ça veut dire Cave Vin on peut mettre ce que l'on veut # c'est Un Prefix pour certaine classes (Sinon par defaut c'est Base je crois). torque.basePrefix = <strong>CV</strong> torque.complexObjectModel = true torque.useClasspath = false torque.useManagers = false # le reste on s'en tape ;) torque.doc.format=html torque.doc.html.normalFont=font-family: Verdana; font-size: 10pt; torque.doc.html.fkColor=afe295 torque.initialID=101 torque.initialIDValue=1000 torque.initialIDStep=20 torque.compile.src.dir=${torque.java.dir} torque.compile.build.dir=${torque.home}/classes # Ca aussi ça ne nous servira pas. torque.compile.debug=on torque.compile.optimize=on torque.compile.deprecation=off |
Voilà votre fichier build.properties est prêt à être utilisé. Pour configurer plus finement le bousin : http://db.apache.org/torque-32/generator/properties-reference.html
La commande suivante va construire le schéma XML depuis les données de notre base :
[ledruide@neptune]# ant jdbc
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 |
Buildfile: build.xml jdbc: [echo] +-----------------------------------------------+ [echo] | | [echo] | Generating XML from JDBC connection ! | [echo] | | [echo] +-----------------------------------------------+ [torque-jdbc-transform] Torque - JDBCToXMLSchema starting [torque-jdbc-transform] Your DB settings are: [torque-jdbc-transform] driver : org.gjt.mm.mysql.Driver [torque-jdbc-transform] URL : jdbc:mysql://localhost:3306/macave [torque-jdbc-transform] user : root [torque-jdbc-transform] schema : MACAVE [torque-jdbc-transform] DB driver sucessfuly instantiated [torque-jdbc-transform] DB connection established [torque-jdbc-transform] Getting table list… [torque-jdbc-transform] Building column/table map… [torque-jdbc-transform] Processing table: bouteilles [torque-jdbc-transform] Processing table: commentaires [torque-jdbc-transform] Processing table: format [torque-jdbc-transform] Processing table: recoltants [torque-jdbc-transform] Processing table: types [torque-jdbc-transform] C:/Perso/dev/DAO/gen/schema/schema.xml [torque-jdbc-transform] Torque - JDBCToXMLSchema finished BUILD SUCCESSFUL Total time: 1 second |
Puis on va aller renommer le fichier de schéma XML que torque vient de générer :
[ledruide@neptune]# mv /home/ledruide/cave/DAO_temp/schema/schema.xml /home/ledruide/cave/DAO_temp/schema/project-schema.xml
Edit : Il se peut que dans le fichier XML généré il y ait UNE erreur : au tout début, le premier attribut de la première balise peut avoir comme valeur le nom du user de votre base alors qu’il devrait y avoir le nom du schema de votre table… le changer au cas ou c’est le cas
Et on lance la tache par defaut :
[ledruide@neptune]# ant
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 |
Buildfile: build.xml main: check-use-classpath: check-run-only-on-schema-change: sql-check: sql: [echo] +------------------------------------------+ [echo] | | [echo] | Generating SQL for YOUR Torque project! | [echo] | | [echo] +------------------------------------------+ sql-classpath: sql-template: [echo] loading templates from /home/ledruide/outils/dev/torque-gen-3.1/templates [torque-sql] Using contextProperties file: /home/ledruide/outils/dev/torque-gen-3.1/build.properties [torque-sql] Generating to file /home/ledruide/cave/DAO_temp/src/sql/report.macave.sql.generation [torque-sql] log4j:ERROR Could not find value for key log4j.appender.org.apache.torque.engine [torque-sql] log4j:ERROR Could not instantiate appender named "org.apache.torque.engine". [torque-sql] 2005-04-14 17:39:05,384 [main] INFO org.apache.torque.engine.database.transform.XmlToAppData - Parsing file: 'project-schema.xml' [torque-sql] 2005-04-14 17:39:05,435 [main] INFO org.apache.torque.engine.database.transform.DTDResolver - Resolver: used database.dtd from 'org.apache.torque.engine.database.transform' package check-use-classpath: check-run-only-on-schema-change: om-check: om: [echo] +------------------------------------------+ [echo] | | [echo] | Generating Peer-based Object Model for | [echo] | YOUR Torque project! | [echo] | | [echo] +------------------------------------------+ om-classpath: om-template: [torque-data-model] Using contextProperties file: /home/ledruide/outils/dev/torque-gen-3.1/build.properties [torque-data-model] Generating to file /home/ledruide/cave/DAO_temp/src/java/report.macave.om.generation [torque-data-model] log4j:ERROR Could not find value for key log4j.appender.org.apache.torque.engine [torque-data-model] log4j:ERROR Could not instantiate appender named "org.apache.torque.engine". [torque-data-model] 2005-04-14 17:39:07,107 [main] INFO org.apache.torque.engine.database.transform.XmlToAppData - Parsing file: 'project-schema.xml' [torque-data-model] 2005-04-14 17:39:07,117 [main] INFO org.apache.torque.engine.database.transform.DTDResolver - Resolver: used database.dtd from 'org.apache.torque.engine.database.transform' package BUILD SUCCESSFUL Total time: 5 seconds |
Voilà c’est fait vos classes java sont créés là : /home/ledruide/cave/DAO_temp/src/java Ils ont déjà l’arborescence de votre package. Tu peux aller voir si tu me crois pas !
2.4 Pour terminer on fait juste un petit torque.properties pour votre appli
Sur la base de celui-ci (par exemple, je ne veux rien imposer…) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
torque.applicationRoot = . log4j.category.org.apache.torque = ALL, org.apache.torque log4j.appender.org.apache.torque = org.apache.log4j.FileAppender log4j.appender.org.apache.torque.file = {torque.applicationRoot}/logs/torque.log log4j.appender.org.apache.torque.layout = org.apache.log4j.PatternLayout log4j.appender.org.apache.torque.layout.conversionPattern = %d [%t] %-5p %c - %m%n log4j.appender.org.apache.torque.append = false torque.database.default=<strong>macave</strong> torque.database.macave.adapter=<strong>mysql</strong> ## Using jndi (pour récupérer le pool de Tomcat ici) torque.dsfactory.<strong>macave</strong>.factory=org.apache.torque.dsfactory.JndiDataSourceFactory torque.dsfactory.<strong>macave</strong>.jndi.path=<strong>java:comp/env/jdbc/macave</strong> torque.dsfactory.<strong>macave</strong>.jndi.java.naming.factory.initial= org.apache.naming.java.javaURLContextFactory torque.dsfactory.<strong>macave</strong>.jndi.java.naming.factory.url.pkgs=org.apache.naming torque.idbroker.cleverquantity=true torque.manager.useCache = true |
On l’appelle torque.properties et on le place dans le classpath de son application (ou ailleurs ! Si vous ne voulez pas le charger via le classpath c’est votre problème !)
C’est tout.
Pour savoir en détail comment on peut configurer tout ça, c’est par là : http://db.apache.org/torque-32/configuration-howto.html
Titre 3. Utilisation des DAO
Là je vais faire super simple et super rapide car la doc de Torque sur le site est suffisante pour comprendre : http://db.apache.org/torque/criteria-howto.html Et il faut fouiller un peu ailleurs pour trouver son bonheur…
3.1 Initialisation
Pour initialiser torque c’est simple : On fait un petit singleton de base pour charger la config une seule fois, un truc du style :
package org.ledruide.cave.init; import java.net.URL; import org.apache.torque.Torque; import org.apache.torque.TorqueException; public class TorqueInit { // ************** METHODES SINGLETON ******************** // private static TorqueInit instance = new TorqueInit(); public synchronized static TorqueInit getInstance() { return instance; } private TorqueInit() { } // ****************************************************** // private static boolean torqueOk = false; public void initTorque() { if (torqueOk == false) { try { URL propsFile = TorqueInit.class.getClassLoader().getResource("torque.properties"); Torque.init(propsFile.getPath()); torqueOk = true; } catch (TorqueException e) { System.err.println("Erreur durant l'initialisation de Torque !"); torqueOk = false; } } } }
Pas besoin de préciser qu’il faut compléter avec votre système de log et traiter les Exception comme il se doit hein ?
Reste plus qu’à aller dans votre code java, et appeler ce singleton au bon endroit de votre application:
TorqueInit.getInstance().initTorque();
Et voilà on peut utiliser nos beau DAO tout propre.
3.2 Recherche
3.2.1 Select par clef primaire
Exemple pour récupérer la bouteille n° 42 :
Bouteilles hips = BouteillesPeer.retrieveByPK(42); System.out.println("Millésime : " + hips.getAnnee()); System.out.println("Reste en cave : " + hips.getQuantite());
etc…
C’est tout 😉 Alors ! c’est pas le pied ?
3.2.2 Select classique
C’est pas bien compliqué. Ici on passe par un Objet intermédiaire qui s’appelle Criteria. Pour en savoir plus sur cet Objet : http://db.apache.org/torque-32/criteria-howto.html
Grosso-modo cet Objet permet de construire des requêtes de toute nature (order by, join, select distinct, comparaisons). Voici ici un exemple de recherche d’un récoltant :
String nomRecoltant = "Chapoutier"; Criteria criteria = new Criteria(); criteria.add(RecoltantsPeer.NOM, (Object) nomRecoltant, Criteria.EQUAL); List resultats = RecoltantsPeer.doSelect(criteria);
Là on se retrouve avec une List de Recoltant. Il ne reste plus qu’à la parcourir cette liste et traiter les résultats.
A la place de Citeria.EQUAL on pouvait mettre Criteria.LIKE, Criteria.NOT_LIKE, Criteria.NOT_EQUAL etc.
3.3 Select all
Ici on va regarder comment étendre les objets générés. Typiquement on voudrait pouvoir récupérer toute la table format afin d’afficher ça dans une combo à l’écran par exemple. Donc on va ouvrir la classe CommentairesPeer et on ajoute une méthode ultra complexe que l’on va appeler doSelectAll par exemple :
public List doSelectAll() throws Exception { Criteria crit = new Criteria(); return doSelect(crit); }
Voilà voilà voilà… je n’ai rien d’autre à dire… Ah si ! Si vous souhaitez ordonner les réponses il faut ajouter un truc comme ça par exemple sur Recoltant : crit.addAscendingOrderByColumn(RecoltantPeer.NOM);
3.4 Insert
Bon donc on a vu comment récupérer des lignes de la table on va maintenant en ajouter des nouvelles. Allons-y je viens de me faire plaisir et je viens d’acheter 4 caisses de 6 bouteilles de Côte-Rôtie “La Mouline” de Monsieur Guigal (Même une caisse finalement ça fais toujours plaisir…) de 1996.
Ici il faut donc utiliser un récoltant existant dans la base (Si si il est déjà créé lui) et ajouter ces bouteilles :
// On commence par rechercher le récoltant : String nomRecoltant = "Guigal"; Criteria criteria = new Criteria(); criteria.add(<strong>RecoltantsPeer.NOM</strong>, (Object) <strong>nomRecoltant</strong>, Criteria.EQUAL); List resultats = <strong>RecoltantsPeer.doSelect(criteria)</strong>; Recoltants recoltant = (Recoltants) resultat.get(0); // Puis on prépare les bouteilles Bouteilles hips = new Bouteilles(); hips.setNom("Côte-Rôtie - La Mouline"); hips.setAnnee(1996); hips.setQuantite(24); hips.setType("Rouge"); hips.setRecoltant(recoltant.getId()); // Et on sauvegarde: hips.<strong>save()</strong>;
Et voilà on à ajouté 24 bouteilles en base. Pour la sauvegarde il y à 2 façons soit la méthode save() de l’objet en question, soit en passant par : BouteillesPeer.doSave(bouteilles);
3.5 Update
Donc on viens d’inviter ses beaux parents et on à été obligé de sortir des bouteilles. En plus comme d’habitude ils sont repartis complètement torchés après t’avoir descendu 4 bouteilles à eux 2 ! Faut mettre le stock à jour (bon je considère que les recherches vous savez faire, donc on y va avec l’ID direct ) :
// On commence par récupérer les bouteilles concernées (id = 42): Bouteilles hips = <strong>BouteillesPeer.retrieveByPK(42)</strong>; // Puis on met à jour les bouteilles en en enlevant 6 (y sont pas tout seuls à boire non plus !) hips.setQuantite(hips.getQuantite - 6); // Et on sauvegarde: hips.save();
Et voilà qui est réglé.
3.6 Delete
On t’as offert une bouteille immonde que tu as du vider dans l’évier donc plutôt que de mettre la quantité de cette bouteilles à 0 tu préfère ne plus jamais en entendre parler et la supprimer de la table ? Pas de soucis, voilà comment faire :
Criteria criteria = new Criteria(); criteria.add(BouteillesPeer.ID, 38); BouteillesPeer.doDelete(criteria);
Titre 4. Conclusion
Torque c’est cool et c’est pratique. Toi aussi utilise Torque et transmet-le. Torque fait partit d’une chaîne de l’espoir, il ne faut pas la briser ! Si dans les 28 secondes tu n’arrive pas à convaincre 42 personnes d’utiliser Torque tu sera maudit à jamais ! Par contre si tu y arrive, sache que tous tes désirs seront réalisés que plus personne n’aura faim dans le monde et que tous tes métro/trains/RER arriveront vide et en même temps que toi sur le quai !
Alors, pour toutes ces raisons, toi aussi devient un Torque User !
@musez-vous bien !
Leave a comment