Requêtes SQL dynamiques avec MyBatis

Les requêtes SQL dynamiques dans MyBatis permettent de construire des instructions SQL conditionnelles et itératives, améliorant la flexibilité des requêtes en base de données.

1. Condition if

La condition if est utilisée pour ajouter des clauses SQL de manière conditionnelle, souvent avec des paramètres de type Map ou entité.


<select id="rechercheEmployes" parameterType="Map" resultType="Employe">
    SELECT * FROM employe e WHERE 1=1
    <if test="idEmp != null">
        AND e.id_emp = #{idEmp}
    </if>
    <if test="nomEmp != null">
        AND e.nom_emp LIKE #{nomEmp}
    </if>
</select>

Exemple de test unitaire :


@Test
public void testRechercheEmployes() {
    Map<String, Object> params = new HashMap<>();
    params.put("idEmp", 1007);
    params.put("nomEmp", "%Jean%");
    List<Employe> liste = mapper.rechercheEmployes(params);
    for (Employe emp : liste) {
        System.out.println(emp);
    }
}

2. Conditions choose, when et otherwise

Ces conditions permettent un choix exclusif, similaire à une structure switch-case.


<select id="rechercheEmployes" parameterType="Map" resultType="Employe">
    SELECT * FROM employe e WHERE 1=1
    <choose>
        <when test="critere == 'id'">
            AND e.id_emp = #{idEmp}
        </when>
        <when test="critere == 'nom'">
            AND e.nom_emp LIKE #{nomEmp}
        </when>
        <otherwise>
            AND e.statut = 'actif'
        </otherwise>
    </choose>
</select>

Exemple de test unitaire :


@Test
public void testRechercheEmployes() {
    Map<String, Object> params = new HashMap<>();
    params.put("critere", "nom");
    params.put("idEmp", 1007);
    params.put("nomEmp", "%Jean%");
    List<Employe> liste = mapper.rechercheEmployes(params);
    for (Employe emp : liste) {
        System.out.println(emp);
    }
}

3. Clause where

La clause where gère automatiquement l'ajout du mot-clé WHERE et supprime les opérateurs AND ou OR initiaux.


<select id="rechercheEmployes" parameterType="Map" resultType="Employe">
    SELECT * FROM employe e
    <where>
        <if test="idEmp != null">
            AND e.id_emp = #{idEmp}
        </if>
        <if test="nomEmp != null">
            AND e.nom_emp LIKE #{nomEmp}
        </if>
    </where>
</select>

Exemple de test unitaire :


@Test
public void testRechercheEmployes() {
    Map<String, Object> params = new HashMap<>();
    params.put("idEmp", 1007);
    params.put("nomEmp", "%Jean%");
    List<Employe> liste = mapper.rechercheEmployes(params);
    for (Employe emp : liste) {
        System.out.println(emp);
    }
}

4. Clause trim

La clause trim offre plus de contrôle que where, permettant de définir des préfixes et sufffixes tout en supprimant les opérateurs indésirables.


<select id="rechercheEmployes" parameterType="Map" resultType="Employe">
    SELECT * FROM employe e
    <trim prefix="WHERE" prefixOverrides="AND|OR">
        <if test="idEmp != null">
            AND e.id_emp = #{idEmp}
        </if>
        <if test="nomEmp != null">
            AND e.nom_emp LIKE #{nomEmp}
        </if>
    </trim>
</select>

Exemple de test unitaire :


@Test
public void testRechercheEmployes() {
    Map<String, Object> params = new HashMap<>();
    params.put("idEmp", 1007);
    params.put("nomEmp", "%Jean%");
    List<Employe> liste = mapper.rechercheEmployes(params);
    for (Employe emp : liste) {
        System.out.println(emp);
    }
}

5. Boucle forEach

La boucle forEach est utilisée pour itérer sur des collections, comme des listes ou des clés de Map, afin de générer des clauses IN dynamiques.

Avec une liste


<select id="rechercheEmployesParIds" parameterType="list" resultType="Employe">
    SELECT * FROM employe e
    <where>
        e.id_emp IN
        <foreach item="identifiant" collection="listeIds" open="(" separator="," close=")">
            #{identifiant}
        </foreach>
    </where>
</select>

Exemple de test unitaire :


@Test
public void testRechercheEmployesParIds() {
    List<Integer> ids = new ArrayList<>();
    ids.add(1066);
    ids.add(1110);
    ids.add(1107);
    List<Employe> liste = mapper.rechercheEmployesParIds(ids);
    for (Employe emp : liste) {
        System.out.println(emp);
    }
}

Avec une Map


<select id="rechercheEmployesParIds" parameterType="Map" resultType="Employe">
    SELECT * FROM employe e
    <where>
        e.id_emp IN
        <foreach item="identifiant" collection="idListe" open="(" separator="," close=")">
            #{identifiant}
        </foreach>
    </where>
</select>

Exemple de test unitaire :


@Test
public void testRechercheEmployesParIds() {
    List<Integer> ids = new ArrayList<>();
    ids.add(1066);
    ids.add(1110);
    ids.add(1107);
    Map<String, Object> params = new HashMap<>();
    params.put("idListe", ids);
    List<Employe> liste = mapper.rechercheEmployesParIds(params);
    for (Employe emp : liste) {
        System.out.println(emp);
    }
}

6. Clause set

La clause set automatise l'ajout du mot-clé SET et supprime la dernière virgule, facilitant les mises à jour dynamiques.


<update id="miseAJourEmploye" parameterType="Employe">
    UPDATE employe e
    <set>
        <if test="nomEmp != null">e.nom_emp = #{nomEmp},</if>
        <if test="departement != null">e.departement = #{departement},</if>
        <if test="salaire != null">e.salaire = #{salaire}</if>
        <where>
            e.id_emp = #{idEmp}
        </where>
    </set>
</update>

Exemple de test unitaire :


@Test
public void testMiseAJourEmploye() {
    Employe emp = new Employe(1066, "NouveauNom", "Technique", 50000.0, null);
    int result = mapper.miseAJourEmploye(emp);
    System.out.println(result);
}

Étiquettes: MyBatis SQL dynamique Java Conditions SQL JUnit

Publié le 3 juin à 18h26