Affichage des articles dont le libellé est jpa. Afficher tous les articles
Affichage des articles dont le libellé est jpa. Afficher tous les articles

19 avril 2011

JPA, et après ...

Ceux qui suivent ce blog connaissent déjà Fonzie, mon petit hack pour éliminer l'écriture de toute la couche persistance d'une application JavaEE dans le cas des requêtes simples, qui constituent d'après le projet sur lequel il a été utilisé plus de 90% des cas d'utilisation.

Avec une API puissante, JPA nous permet de construire des requêtes et du code d'accès à la base pour quasiment tous les cas de figure (bien sûr il reste quelques exceptions, sinon le groupe de travail JPA 2.1 serait au chômage). Seulement, cette API est parfois surdimensionnée pour des requêtes simples, de la forme select * from Truc where bibi = 'foc'

Fonzie était inspiré par Grails (GORM), mais n'est pas, loin s'en faut, la seule tentative de simplifier le codage des accès à la base de données. Il y avait déjà Hades, présenté il y a deux ans à Devoxx, qui permet de déclarer un Repository sous forme d'interface et de laisser le framework analyser les noms de méthodes pour en déduire les requêtes. Il y a depuis peu Spring-Data et son module JPA qui reprend la même idée avec la force de frappe de SpringSource/VMWare.

C'est bien, mais certains (j'en suis) regretterons que tous ces facilitateurs ne valident pas les requêtes définies par les programmeurs. Il faut attendre l'exécution pour que le framework nous indique qu'une méthode ne peut être interprétée. Un refactoring de trop et hop, tout plante.

Pour répondre à cette attente il y a donc, depuis JPA 2.0, l'API Criteria. Contrairement à Hibernate Criteria, celle-ci est totalement type-safe et valide la construction des requêtes dès la compilation. C'est donc une très bonne chose a priori. Sauf que ... Criteria s'impose de couvrir 100% des capacités de JPQL, et aboutit à une syntaxe extrêmement lourde et très peu lisible; jugez plutôt, pour la même requête pourtant triviale :

CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<truc> query = cb.createQuery(Truc.class);

        Root<truc> truc = query.from(Truc.class);
        query.where(cb.eq( truc.<string>get( Truc_.bibi ), "foc" ));

        TypedQuery<truc> tq = em.createQuery(query);

L'informatique semble avoir horreur du vide, aussi un framework se propose de combler ce manque de lisibilité. L'idée est de générer (avec un annotation processor Java6) un métamodel qui soit spécifique aux requêtes QueryDSL (les classes Q*), et pas juste le métamodel "neutre" défini par JPA (mais qui par contre pourait servir à d'autres frameworks ... si l'API était sortie du package javax.persistence). QueryDSL, qui d'ailleurs peut accéder à bien plus que JPA, propose de construire des requêtes avec une excellente lisibilité, et 100% type-safe :

import static QTruc.truc;

   public List<Truc> getBibiFoc() {
        return from( truc )
              .where( truc.bibi.eq( "foc" ) )
              .list( truc );
   }

C'est pas beau ça ? Aux parenthèses près, on se croirait sous .Net en train de coder avec LINQ !
Alors, évidemment, il est probable qu'en creusant un peu queryDSL ne supporte pas 100% de JPQL, et ne permette pas de faire un LEFT OUTER JOIN sur une Map d' Embeddable, mais en même temps, le jour où j'aurais vraiment besoin de ça, ce n'est pas de coder le Repository qui exécute cette requête qui va me coûter mais plutôt de comprendre comment on a pu pondre un modèle pareil...

13 août 2008

GWT et JPA, main dans la main ?

J'ai raté la sortie d'Hibernate4Gwt en version 1.1. En plus de corriger quelques bugs, cette version est une mise à niveau pour GWT 1.5.

Pour ceux qui ne connaissent pas, H4GWT permet d'utiliser les entités Hibernate/JPA comme données dans une application GWT, ce qui comporte pas mal de complications techniques, habilement résolues par Bruno Marchesson.

Avec le support de Java5 dans GWT, et une "émulation" des annotations JPA, il devient possible d'utiliser le même modèle métier depuis la couche de persistance jusqu'à l'IHM web. Tout le code de type "contrôles et validation" peut alors être placé dans les setters du modèle, c'est à dire là ou il est finalement le plus logique de le placer !

Je n'ai pas pu tester personnellement (mon projet actuel ne s'y prête pas) mais l'idée me plaît beaucoup et me fait définitivement apprécier le concept phare derrière GWT : un langage et une plateforme pour toute la chaîne de développement.