Tag: java, mybatis, orm, sql, jdbc, mapper, spring
Livello: intermedio
TL;DR: Framework di persistenza per Java che mappa il risultato delle query SQL su oggetti. Offre controllo totale sul codice SQL a differenza dei tradizionali ORM come Hibernate.
Non è un ORM completo ma un "SQL Mapper": il focus è sulla scrittura manuale delle query SQL.
Mantiene una separazione netta tra il codice Java e le query (generalmente scritte in file XML).
Consente la creazione di query dinamiche tramite costrutti XML specifici (<if>, <choose>, <where>, <foreach>).
Utilizza #{param} per inserire parametri in modo sicuro tramite PreparedStatement (previene SQL injection).
Utilizza ${param} per l'iniezione diretta di testo nella query (da usare con cautela, es. nomi colonne/tabelle dinamici).
Supporta mappature complesse per relazioni uno-a-uno (<association>) e uno-a-molti (<collection>).
Gestisce cache di primo livello (a livello di sessione) e secondo livello (a livello di namespace globale).
Si integra nativamente con Spring e Spring Boot tramite il pacchetto mybatis-spring-boot-starter.
Q: Qual è la differenza principale tra MyBatis e Hibernate?R: Hibernate mappa le classi alle tabelle e genera le query automaticamente. MyBatis richiede di scrivere le query a mano, dandomi il controllo assoluto sulle performance e sulle ottimizzazioni del database.
Q: Qual è la differenza tra #{} e ${}?R: #{} usa i PreparedStatement di JDBC ed è sicuro contro le SQL injection. ${} inserisce la stringa in modo diretto (string substitution), lo uso solo per parametri strutturali come nomi di tabelle o colonne se strettamente necessario.
Q: Come risolvi il problema N+1 select in MyBatis?R: Sfrutto le join SQL direttamente nella query e uso il tag <collection> o <association> nel <resultMap> per mappare i dati annidati, evitando query aggiuntive per ogni record estratto.
Utilizzare ${} per passare parametri inseriti dall'utente, creando vulnerabilità SQL Injection.
Creare file XML eccessivamente complessi con troppi tag dinamici, rendendo l'SQL incomprensibile e difficile da debuggare.
Dimenticare di configurare correttamente le annotazioni @Param nei metodi dell'interfaccia Java, causando errori nel binding dei parametri.
Non disabilitare o svuotare correttamente la cache di primo livello durante elaborazioni batch massicce, causando OutOfMemoryError.
<!-- UserMapper.xml: Esempio di mapping dinamico -->
<mapper namespace="com.example.mapper.UserMapper">
<resultMap id="UserResult" type="com.example.dto.User">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="email" column="email" />
</resultMap>
<select id="findUsers" resultMap="UserResult">
SELECT id, username, email
FROM users
<where>
<if test="status != null">
status = #{status}
</if>
<if test="role != null">
AND role = #{role}
</if>
</where>
</select>
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
INSERT INTO users (username, email)
VALUES (#{username}, #{email})
</insert>
</mapper>
Java
// UserMapper.java: Interfaccia corrispondente
@Mapper
public interface UserMapper {
List<User> findUsers(@Param("status") String status, @Param("role") String role);
void insertUser(User user);
}
[ ] Implementazione e configurazione della cache di secondo livello (es. con Redis o Ehcache).
[ ] Utilizzo dei plugin/interceptor MyBatis per audit logging o paginazione custom.
[ ] Gestione del TypeHandler per mappare tipi Java complessi su tipi database nativi (es. JSON in PostgreSQL).
MyBatis 3 Reference Documentation