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.
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.
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.
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.
```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>
```
[ ] 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