MyBatis Mapper — Cheat Sheet

Tag: java, mybatis, sql, orm, persistence, backend, database

Livello: intermedio

TL;DR: I Mapper di MyBatis associano metodi Java a query SQL native via XML o annotazioni, offrendo pieno controllo sull'SQL senza astrazioni ORM pesanti.

Concetti chiave

Interfaccia Java pura associata a statement SQL tramite XML dedicato o annotazioni Java.

Disaccoppiamento completo tra query SQL e codice applicativo business.

SqlSession crea dinamicamente l'implementazione proxy dell'interfaccia mapper via reflection.

Binding dei parametri tramite annotazione @Param per gestire argomenti multipli.

ResultMap mappa colonne del result set su proprietà complesse degli oggetti Java.

Supporto SQL dinamico nativo con tag <if>, <choose>, <where>, <foreach> e <trim>.

Differenza tra #Param} con PreparedStatement sicuro e ${param} con concatenazione SQL grezza.

Caching di primo livello per SqlSession e secondo livello opzionale per namespace.

Domande tipiche e risposte pronte

Q: Qual è la differenza sostanziale tra #Param} e ${param} nei mapper MyBatis?R: Uso #Param} per generare PreparedStatement con placeholder ?, garantendo protezione contro SQL injection; uso ${param} solo per valori dinamici non parametrizzabili come nomi di tabelle.

Q: Perché preferire un mapper MyBatis rispetto a Hibernate/JPA in contesti specifici?R: Scelgo MyBatis quando ho query complesse, stored procedure esistenti o bisogno di ottimizzare manualmente ogni singola istruzione SQL senza l'overhead di una gestione complessa dello stato dell'entità.

Q: Come gestisci mapping nidificati o relazioni 1-a-N nei mapper?R: Definisco un <resultMap> con elementi <association> per relazioni one-to-one e <collection> per relazioni one-to-many, evitando query N+1 tramite join dedicati.

Insidie e errori comuni

Uso improprio di ${param} su input utente, con conseguente vulnerabilità a SQL Injection.

Dimenticare l'annotazione @Param su metodi con due o più argomenti primitivi.

Disallineamento tra package/nome interfaccia Java e attributo namespace dell'XML.

Mancata corrispondenza tra id del metodo Java e attributo id del tag SQL XML.

Problema del loop N+1 usando fetch nidificati invece di resultMap con join esplicita.

Tag <where> omesso causando errori sintattici con clausole AND o OR iniziali.

Snippet e comandiJava

```public interface UserMapper {

User findById(@Param("id") Long id);

List<User> searchUsers(@Param("status") String status, @Param("names") List<String> names);

int insertUser(User user);

}

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

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.mapper.UserMapper">

<select id="findById" resultType="com.example.model.User">

SELECT id, username, email FROM users WHERE id = #{id}

</select>

<select id="searchUsers" resultType="com.example.model.User">

SELECT id, username, email FROM users

<where>

<if test="status != null">

status = #{status}

</if>

<if test="names != null and !names.isEmpty()">

AND username IN

<foreach item="name" collection="names" open="(" separator="," close=")">

#{name}

</foreach>

</if>

</where>

</select>

</mapper>

```

Da ripassare

[ ] Sintassi avanzata del tag <trim> per customizzare prefissi e suffissi SQL

[ ] Configurazione e gestione del cache di secondo livello con Redis o Ehcache

[ ] Utilizzo di TypeHandler personalizzati per tipi enumerati complessi o JSON

[x] Differenza tra #Param} e ${param}

[x] Struttura base di un ResultMap con collection e association

Jarvis Interviews
Jarvis