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

JPA Java Discussion :

Tutoriel pour apprendre où définir au mieux une NamedQuery JPA


Sujet :

JPA Java

  1. #1
    Responsable Java & Kotlin

    Avatar de Mickael Baron
    Homme Profil pro
    Ingénieur de Recherche en Informatique
    Inscrit en
    juillet 2005
    Messages
    14 908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche en Informatique
    Secteur : Service public

    Informations forums :
    Inscription : juillet 2005
    Messages : 14 908
    Points : 72 615
    Points
    72 615
    Par défaut Tutoriel pour apprendre où définir au mieux une NamedQuery JPA
    Bonjour,

    François-Xavier Robin nous propose un tutoriel pour apprendre où définir au mieux une NamedQuery proposée dans la spécification JPA via le langage Java

    Pour consulter le tutoriel : https://fxrobin.developpez.com/tutor...a-named-query/

    N'hésitez pas à laisser des commentaires à la suite.

    Mickael BARON pour l'équipe Java de Developpez.com

    Retrouver les meilleurs cours et tutoriels pour apprendre le stockage de données avec JPA et le langage Java
    Responsable Java de Developpez.com (Twitter et Facebook)
    Besoin d"un article/tutoriel/cours sur Java, consulter la page cours
    N'hésitez pas à consulter la FAQ Java et à poser vos questions sur les forums d'entraide Java
    --------
    Ingénieur de Recherche en informatique au LIAS / ISAE-ENSMA
    Page de Developpez.com : mbaron.developpez.com
    Twitter : www.twitter.com/mickaelbaron
    Blog : mickael-baron.fr
    LinkedIn : www.linkedin.com/in/mickaelbaron
    DBLP : dblp.uni-trier.de/pers/hd/b/Baron:Micka=euml=l

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : avril 2007
    Messages : 25 481
    Points : 48 811
    Points
    48 811
    Par défaut
    Article intéressant sur le concept. Je me sens d'autant plus concerné que je joue avec de gros projets où de multiples applications font une réutilisation d'un même data model. Et dans ce cas là, les @NamedQuery, c'est très limité, on ne peux pas changer le modèle à chaque fois qu'on veux changer une query dans une appli. Et le xml, c'est galère en refactoring . Ton article va apporter de l'eau à mon moulin


    J'aurais cependant plusieurs remarques:

    1) ça a l'air bête, mais le projet maven sur github ne fonctionne pas 'out of the box' et crache des "No Persistence provider". C'est dommage vu qu'il viens en appuis de l'article.

    2) VII. Le référenceur programmatique de NamedQuery => Ben je propose "VII. Enrôler les named queries"

    3) C'est du chipo, mais lombok peut faire mieux. Pas besoin de répéter les getter / setter, d'ajouter le toString, etc alors que l'annotation @Data faite déjà tout le travail il me semble (mea culpa, je n'ai pas vraiment testé)
    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
    @Entity
    @Table(name="VIDEO_GAME")
    @Data
    public class VideoGame implements Serializable
    {
    	@GeneratedValue
    	@Setter(AccessLevel.PRIVATE)
    	private Long id;
     
    	private String name;
     
    	@Enumerated(EnumType.STRING)
    	@Column(name="GAME_GENRE")
    	private GameGenre gameGenre;
     
    	public VideoGame(String name, GameGenre gameGenre)
    	{
    		super();
    		this.name = name;
    		this.gameGenre = gameGenre;
    	}
     
    }
    3) Même si une partie très intéressante de l'architecture a été faite, je trouve que la partie enum pourrait être plus élégante facile à maintenir.

    Elle contient pas mal de boilerplate code à réécrire sur chaque enum contenant des query custom. Dans ton exemple il n'y a que "VideoGameQuery", mais en pratique on peut se retrouver avec des centaines de query à gérer.
    Une solution basique serait de laisser lombok gérer les getters et constructeurs sur le champ query, comme c'est le cas dans l'entity.
    Une solution plus élégante à mon gout serait de jouer avec les annotations et les default methods de l'interface
    Exemple:
    une annotation custom:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value={FIELD})
    public @interface EnumQuery {
        public String query() default "";
    }
    une interface avec de la logique:
    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
    public interface RegistrableQuery
    {
    	/**
             * @return la requête JPQL.
             */
    	default String getQuery(){
    		try {
    			EnumQuery annotation = this.getClass().getField(((Enum<?>) this).name()).getDeclaredAnnotation(EnumQuery.class);
    			if (annotation != null){
    				return annotation.query();
    			} else {
    				throw new RuntimeException("enum "+this+" does not have a @EnumQuery annotation");
    			}
    		} catch (NoSuchFieldException e) {
    			throw new RuntimeException(this+" is a broken enum according to java specs. Should not happend");
    		} catch (ClassCastException e) {
    			throw new RuntimeException(this+" is not an enum");
    		}
    	};
     
    	/**
             * @return l'identifiant de la requête JPQL.
             */
    	default String getIdentifier() {
    		return String.format("%s_%s", this.getClass(), ((Enum<?>)this).name());
    	}
    }
    (L'idéal aurait été une abstract class plutot que des methods default, mais enum de m*** oblique quoi )

    L'enum devient alors beaucoup plus simple à lire à mon avis:
    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
    public enum VideoGameQuery implements RegistrableQuery
    {
        /**
         * retourne les VideoGame en fonction de leur genre. 
         * Argument JPQL attendu : gameGenre de type GameGenre.     
         */
        @EnumQuery(query="SELECT vg FROM VideoGame vg WHERE vg.gameGenre = :gameGenre")
        FIND_BY_GENRE,
     
        /**
         * retourne les VideoGame en fonction d'un nom approchant (LIKE). 
         * Argument JPQL attendu : name de type String.
         */
     
        @EnumQuery(query="SELECT vg FROM VideoGame vg WHERE vg.name LIKE :name")
        FIND_BY_NAME_LIKE;
    }
    3) je ne sais pas compter jusque 4 visiblement.

  3. #3
    Membre chevronné
    Avatar de fxrobin
    Homme Profil pro
    Architecte SI, Java Fan, API Manager
    Inscrit en
    novembre 2007
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Architecte SI, Java Fan, API Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : novembre 2007
    Messages : 875
    Points : 2 112
    Points
    2 112
    Par défaut
    Bonjour tchize_,

    merci pour ton retour, ça fait plaisir.

    Pour tes remarques :

    1- ah oui étrange, je vérifierai le projet sur GitHub dès que possible. (L'article date de 2018 et a été intégré à DVP que récemment, donc il me faut vérifier l'ensemble).

    2- oui, ton titre est bien mieux trouvé que le mien.

    3- Alors pour l'usage de Lombok, je suis plus mitigé. Ma réponse est incluse dans mon article : https://fxrobin.developpez.com/tutor...ur-experience/

    3 :-) - complètement d'accord sur tes propositions. Une petite "critique cependant" sur cette dernière : si une valeur de l'enum ne comporte l'annotation, ce n'est qu'au Runtime qu'on s'en rend compte.
    Avec le constructeur qui impose une requête en paramètre c'est détecté à la compilation. Mais bon, on peut être mettre une requête complètement bidon aussi, je le reconnais.

    3 - à bah moi aussi :-)

    Au final je ferai un update de l'article sur mon blog en premier : https://www.fxjavadevblog.fr/Enum-JPA-Named-Query/
    Puis sur DVP.

    Merci à toi.
    Moins on code, moins il y a de bug ... et vice-versa ainsi qu'inversement ...

  4. #4
    Membre chevronné
    Avatar de fxrobin
    Homme Profil pro
    Architecte SI, Java Fan, API Manager
    Inscrit en
    novembre 2007
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Architecte SI, Java Fan, API Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : novembre 2007
    Messages : 875
    Points : 2 112
    Points
    2 112
    Par défaut
    Voilà, le projet sur GitHub est "réparé".
    Il construit maintenant un "uber-jar" en incluant toutes dépendances.
    Il suffit de faire un "mvn package" puis "java -jar ./target/named-queries-demo-0.0.1-SNAPSHOT.jar"

    F.X.
    Moins on code, moins il y a de bug ... et vice-versa ainsi qu'inversement ...

Discussions similaires

  1. Réponses: 3
    Dernier message: 23/07/2018, 17h48
  2. Réponses: 0
    Dernier message: 06/03/2018, 16h32
  3. Tutoriels pour apprendre a créer une application eclipse
    Par NiHiL dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 21/12/2006, 22h53

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