DéveloppeurWeb.Com
    DéveloppeurWeb.Com
    • Agile Zone
    • AI Zone
    • Cloud Zone
    • Database Zone
    • DevOps Zone
    • Integration Zone
    • Web Dev Zone
    DéveloppeurWeb.Com
    Home»Uncategorized»Exprimer des requêtes Hibernate en tant que flux Java de type sécurisé
    Uncategorized

    Exprimer des requêtes Hibernate en tant que flux Java de type sécurisé

    janvier 30, 2023
    Exprimer des requêtes Hibernate en tant que flux Java de type sécurisé
    Share
    Facebook Twitter Pinterest Reddit WhatsApp Email

    Même si le générateur de critères JPA est expressif, les requêtes JPA sont souvent tout aussi détaillées et l’API elle-même peut être peu intuitive à utiliser, en particulier pour les nouveaux arrivants. Dans l’écosystème Quarkus, Panache est un remède partiel à ces problèmes lors de l’utilisation d’Hibernate. Pourtant, je me retrouve à jongler avec les méthodes d’assistance de Panache, les énumérations préconfigurées et les chaînes brutes lors de la composition de tout sauf de la plus simple des requêtes. Vous pourriez prétendre que je suis simplement inexpérimenté et impatient ou, au lieu de cela, reconnaître que l’API parfaite est facile à utiliser pour tout le monde. Ainsi, l’expérience utilisateur d’écriture de requêtes JPA peut être encore améliorée dans cette direction.

    Introduction

    L’un des défauts restants est que les chaînes brutes ne sont pas de type sécurisé par nature, ce qui signifie que mon IDE me rejette l’aide de la complétion de code et me souhaite au mieux bonne chance. En revanche, Quarkus facilite les relances d’applications en une fraction de seconde pour émettre des verdicts rapides sur mon code. Et rien ne vaut la joie sincère et la véritable surprise lorsque j’ai composé une requête de travail sur la cinquième, plutôt que la dixième, tentative…

    Dans cet esprit, nous avons construit la bibliothèque open-source JPAstreamer pour rendre le processus d’écriture des requêtes Hibernate plus intuitif et moins chronophage tout en laissant intacte votre base de code existante. Il atteint cet objectif en permettant aux requêtes d’être exprimées sous forme de flux Java standard. Lors de l’exécution, JPAstreamer traduit le pipeline de flux en une requête HQL pour une exécution efficace et évite de matérialiser autre chose que les résultats pertinents.

    Prenons un exemple : dans une base de données aléatoire, il existe une table appelée Person représenté dans une application Hibernate par la norme suivante Entity:

    @Entity
    @Table(name = "person")
    public class Person {
      
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "person_id", nullable = false, updatable = false)
        private Integer actorId;
    
        @Column(name = "first_name", nullable = false, columnDefinition = "varchar(45)")
        private String firstName;
    
        @Column(name = "last_name", nullable = false, columnDefinition = "varchar(45)")
        private String lastName;
    
        @Column(name = "created_at", nullable = false, updatable = false)
        private LocalDateTime createdAt;
    
    	// Getters for all fields will follow from here 
    }

    Pour aller chercher le Person avec un identifiant de 1 en utilisant JPAstreamer, tout ce dont vous avez besoin est le suivant :

    @ApplicationScoped
    public class PersonRepository {
    	
        @PersistenceContext
        EntityManagerFactory entityManagerFactory;
    
        private final JPAStreamer jpaStreamer;
    
        public PersonRepository EntityManagerFactory entityManagerFactory) {
    		jpaStreamer = JPAStreamer.of(entityManagerFactory); <1>
        }
    
        @Override
        public Optional<Person> getPersonById(int id) {
            return this.jpaStreamer.from(Person.class) <2>
                .filter(Person$.personId.equal(id)) <3>
                .findAny();
        }
      
    }

    <1> Initialisez JPAstreamer en une seule ligne, le fournisseur JPA sous-jacent gère la configuration de la base de données.

    <2> La source du flux est définie pour être le Person tableau.

    <3> L’opération de filtrage est traitée comme un SQL WHERE clause et la condition est exprimée de manière sécurisée avec les prédicats JPAstreamer (plus à ce sujet à suivre).

    Bien qu’il semble que JPAstreamer fonctionne sur tous Person objets, le pipeline est optimisé pour une seule requête, dans ce cas :

    select
        person0_.person_id as person_id1_0_,
        person0_.first_name as first_na2_0_,
        person0_.last_name as last_nam3_0_,
        person0_.created_at as created_4_0_,
    from
        person person0_
    where
        person0_.person_id=1

    Ainsi, seul le Person correspondant aux critères de recherche est toujours matérialisé.

    Ensuite, nous pouvons regarder un exemple plus complexe dans lequel je recherche Personest composé d’un prénom se terminant par un « A » et d’un nom de famille commençant par un « B ». Les correspondances sont triées principalement par prénom et deuxièmement par nom de famille. Je décide en outre d’appliquer un décalage de 5, en excluant les cinq premiers résultats, et de limiter le total des résultats à 10. Voici le pipeline de flux pour accomplir cette tâche :

    List<Person> list = jpaStreamer.stream(Person.class)
    	.filter(Person$.firstName.endsWith("A").and(Person$.lastName.startsWith("B"))) <1>
    	.sorted(Person$.firstName.comparator().thenComparing(Person$.lastName.comparator())) <2>
    	.skip(5) <3> 
    	.limit(10) <4>
    	.collect(Collectors.toList())
    

    <1> Les filtres peuvent être combinés avec les opérateurs et/ou.

    <2> Filtrez facilement sur une ou plusieurs propriétés.

    <3> Passer les 5 premières personnes.

    <4> Retournez au plus 10 personnes.

    Dans le contexte des requêtes, les opérateurs de flux filtrer, trier, limiter et ignorer ont tous un mappage naturel qui rend la requête résultante expressive et intuitive à lire tout en restant compacte.

    Cette requête est traduite par JPAstreamer en la déclaration HQL suivante :

    select
        person0_.person_id as person_id1_0_,
        person0_.first_name as first_na2_0_,
        person0_.last_name as last_nam3_0_,
        person0_.created_at as created_4_0_,
    from
        person person0_
    where
        person0_.person_id=1
    where
        (person0_.first_name like ?) 
        and (person0_.last_name like ?) 
    order by
        person0_.first_name asc,
        person0_.last_name asc limit ?, ?

    Comment fonctionne JPAstreamer

    Bon, ça a l’air simple. Mais comment ça marche? JPAstreamer utilise un processeur d’annotation pour former un méta-modèle au moment de la compilation. Il inspecte toutes les classes marquées avec l’annotation JPA standard @Entityet pour chaque entité Foo.classun correspondant Foo$.class est créé. Les classes générées représentent les attributs d’entité comme Fields utilisé pour former des prédicats sur le formulaire User$.firstName.startsWith("A") qui peut être interprété par l’optimiseur de requête de JPAstreamer.

    Il convient de répéter que JPAstreamer ne modifie ni ne perturbe la base de code existante, mais étend simplement l’API pour gérer les requêtes de flux Java.

    Installation de l’extension JPAstreamer

    JPAstreamer est installé comme n’importe quelle autre extension Quarkus, en utilisant une dépendance Maven :

    <dependency>
    	<groupId>io.quarkiverse.jpastreamer</groupId>
    	<artifactId>quarkus-jpastreamer</artifactId>
    	<version>1.0.0</version>
    </dependency>

    Une fois la dépendance ajoutée, reconstruisez votre application Quarkus pour déclencher le processeur d’annotations de JPAstreamer. L’installation est terminée une fois que les champs générés résident dans /target/generated-sources; vous les reconnaîtrez par le $ final dans les noms de classe, par exemple, Person$.class.

    Note: JPAstreamer nécessite un fournisseur JPA sous-jacent, tel que Hibernate. Pour cette raison, JPAstreamer n’a pas besoin de configuration supplémentaire car l’intégration de la base de données est prise en charge par le fournisseur JPA.

    JPAstreamer et Panache

    Tout fan de Panache remarquera que JPAstreamer partage certains de ses objectifs avec Panache, en simplifiant de nombreuses requêtes courantes. Pourtant, JPAstreamer se distingue en instillant plus de confiance dans les requêtes grâce à son interface de flux de type sécurisé. Cependant, personne n’est obligé de faire un choix car Panache et JPAstreamer fonctionnent de manière transparente l’un à côté de l’autre.

    Note: Voici un exemple d’application Quarkus qui utilise à la fois JPAstreamer et Panache.

    Au moment de la rédaction, JPAstreamer ne prend pas en charge le modèle d’enregistrement actif de Panache, car il s’appuie sur les entités JPA standard pour générer son méta-modèle. Cela changera probablement dans un proche avenir.

    Résumé

    JPA en général et Hibernate ont grandement simplifié l’accès à la base de données des applications, mais son API force parfois une complexité inutile. Avec JPAstreamer, vous pouvez utiliser JPA tout en gardant votre base de code propre et maintenable.

    Share. Facebook Twitter Pinterest LinkedIn WhatsApp Reddit Email
    Add A Comment

    Leave A Reply Cancel Reply

    Catégories

    • Politique de cookies
    • Politique de confidentialité
    • CONTACT
    • Politique du DMCA
    • CONDITIONS D’UTILISATION
    • Avertissement
    © 2023 DéveloppeurWeb.Com.

    Type above and press Enter to search. Press Esc to cancel.