Introduction à MyBatis : Maîtriser le framework ORM semi-automatique

MyBatis est un framework de persistance léger qualifié d'ORM semi-automatique. Contrairement aux ORM complets, il offre un contrôle total sur les requêtes SQL personnalisées, les procédures stockées et le mappage objet-relationnel avancé. Bien qu'il soit souvent associé à MySQL, il s'intègre parfaitement avec d'autres systèmes comme PostgreSQL.

1. Configuraton et initialisation

Pour commencer avec MyBatis dans un environnement Spring Boot, vous devez d'abord intégrer les dépendances nécessaires dans votre fichier pom.xml.

<!-- Starter MyBatis pour Spring Boot -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.4</version>
</dependency>

<!-- Driver pour MySQL -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

Ensuite, configurez la connexion à la base de données dans le fichier application.yml :

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ma_base_donnees?characterEncoding=utf8&useSSL=false
    username: admin
    password: secret_password
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true # Conversion automatique snake_case vers camelCase

2. Opérations de base via Annotations

L'utilisation d'annotations est la méthode la plus rapide pour définir des opérations CRUD simples directement dans l'interface Mapper.

Lecture (Select)

@Select("SELECT * FROM t_client WHERE id_client = #{id}")
Client findClientById(Integer id);

@Select("SELECT * FROM t_client")
List<Client> fetchAllClients();

Si les noms de colonnes SQL ne correspondent pas aux propriétés Java, utilisez @Results ou des alias SQL :

@Results(id = "ClientMap", value = {
    @Result(column = "nom_famille", property = "nom"),
    @Result(column = "date_inscription", property = "dateInscription")
})
@Select("SELECT * FROM t_client")
List<Client> getAllWithMapping();

Insertion (Insert)

Pour récupérer la clé primaire générée automatiquement après une insertion, utilisez l'annotation @Options.

@Insert("INSERT INTO t_client(pseudo, email) VALUES(#{pseudo}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "idClient")
Integer saveClient(Client client);

Mise à jour et Suppression

@Update("UPDATE t_client SET email = #{nouveauEmail} WHERE id_client = #{id}")
Integer updateEmail(String nouveauEmail, Integer id);

@Delete("DELETE FROM t_client WHERE id_client = #{id}")
Integer removeClient(Integer id);

3. Utilisation des fichiers de configuration XML

Pour des requêtes complexes, le format XML est préférable car il sépare le code Java de la logique SQL. Déclarez d'abord l'emplacement des mappers dans votre configuration :

mybatis:
  mapper-locations: classpath:mappers/*.xml

Structure type d'un fichier ClientMapper.xml :

<?xml version="1.0" encoding="UTF-8"?>

<mapper namespace="com.projet.mapper.ClientMapper">

    <resultMap id="ClientResultMap" type="com.projet.model.Client">
        <id column="id_client" property="idClient" />
        <result column="nom_client" property="nom" />
    </resultMap>

    <select id="findByName" resultMap="ClientResultMap">
        SELECT * FROM t_client WHERE nom_client = #{nom}
    </select>

</mapper>

Note technique : Dans les fichiers XML, le caractère "inférieur à" (<) doit être échappé en &lt; pour éviter les erreurs d'analyse syntaxique.

4. Distinction entre #{} et ${}

MyBatis propose deux manières d'injecter des paramètres :

  • #{} (Reecommandé) : Utilise des requêtes préparées (PreparedStatement). Les valeurs sont échappées, ce qui empêche les injections SQL et améliore les performances.
  • ${} : Effectue une simple concaténation de chaînes. Utile uniquement pour injecter des noms de tables, de colonnes ou des clauses de tri (ex: ORDER BY ${colonne}). Attention : Risque élevé d'injection SQL.

5. SQL Dynamique

Le SQL dynamique permet de consturire des requêtes modulaires en fonction des paramètres fournis à l'exécution.

La balise <if> et <where>

La balise <where> est intelligente : elle n'ajoute le mot-clé "WHERE" que si au moins une condition est remplie et supprime les "AND" ou "OR" superflus au début.

<select id="rechercherFiltre" resultType="com.projet.model.Client">
    SELECT * FROM t_client
    <where>
        <if test="ville != null">
            AND localite = #{ville}
        </if>
        <if test="statut != null">
            AND actif = #{statut}
        </if>
    </where>
</select>

La balise <foreach>

Indispensable pour les clauses IN lors du passage d'une liste de paramètres.

<delete id="supprimerBatch">
    DELETE FROM t_client WHERE id_client IN
    <foreach collection="listeIds" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</delete>

La balise <set>

Utilisée pour les mises à jour dynamiques, elle gère automatiquement les virgules de fin.

<update id="majProfil">
    UPDATE t_client
    <set>
        <if test="tel != null">telephone = #{tel},</if>
        <if test="adresse != null">adresse_postale = #{adresse},</if>
    </set>
    WHERE id_client = #{id}
</update>

6. Réutilisation avec <sql> et <include>

Pour éviter la duplication de colonnes ou de conditions récurrentes, vous pouvez définir des fragments SQL réutilisables.

<sql id="colonnes_de_base">
    id_client, nom, email, date_creation
</sql>

<select id="trouverTous" resultType="com.projet.model.Client">
    SELECT <include refid="colonnes_de_base" /> FROM t_client
</select>

Étiquettes: MyBatis Java Spring Boot ORM SQL

Publié le 23 août à 02h20