Preparación del Entorno y Dependencias
Para integrar MyBatis en un proyecto Java tradicional sin herramientas de construcción automatizada, es necesario descargar e importar manualmente los archivos JAR requeridos en el classpath del proyecto. Las dependencias fundamentales son:
- MyBatis Core: El núcleo del framework (ej.
mybatis-3.5.x.jar). - Controlador JDBC: El driver específico para la base de datos (ej.
mysql-connector-java-8.x.jar). - JUnit: Para la ejecución de pruebas unitarias (ej.
junit-4.x.jar).
Esquema de Base de Datos
Antes de configurar el framework, se debe preparar la base de datos. A continuación, se muestra un esquema básico para una tabla de usuarios:
CREATE DATABASE IF NOT EXISTS bd_mybatis;
USE bd_mybatis;
CREATE TABLE usuario (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre_usuario VARCHAR(50) NOT NULL,
contrasena VARCHAR(100) NOT NULL,
edad INT,
genero VARCHAR(10),
fecha_nacimiento DATE
);
Configuración de Propiedades y Núcleo de MyBatis
Es una buena práctica externalizar las credenciales de la base de datos. Cree un archivo llamado db-config.properties:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bd_mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
jdbc.username=root
jdbc.password=root
A continuación, configure el archivo principal de MyBatis, mybatis-core.xml. Este archivo define los alias, el entorno de ejecución y los mapeadores:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<properties resource="db-config.properties"/>
<typeAliases>
<package name="modelo"/>
</typeAliases>
<environments default="entorno_desarrollo">
<environment id="entorno_desarrollo">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapeos/UsuarioMapper.xml"/>
</mappers>
</configuration>
Modelo de Dominio (Entidad)
La clase Java debe reflejar la estructura de la tabla. Los nombres de los atributos deben coincidir con las columnas de la base de datos para que el mapeo automático funcione correctamente, o se deben usar alias en las consultas.
package modelo;
import java.util.Date;
public class Usuario {
private Integer id;
private String nombreUsuario;
private String contrasena;
private Integer edad;
private String genero;
private Date fechaNacimiento;
public Usuario() {}
public Usuario(String nombreUsuario, String contrasena, Integer edad, String genero, Date fechaNacimiento) {
this.nombreUsuario = nombreUsuario;
this.contrasena = contrasena;
this.edad = edad;
this.genero = genero;
this.fechaNacimiento = fechaNacimiento;
}
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getNombreUsuario() { return nombreUsuario; }
public void setNombreUsuario(String nombreUsuario) { this.nombreUsuario = nombreUsuario; }
public String getContrasena() { return contrasena; }
public void setContrasena(String contrasena) { this.contrasena = contrasena; }
public Integer getEdad() { return edad; }
public void setEdad(Integer edad) { this.edad = edad; }
public String getGenero() { return genero; }
public void setGenero(String genero) { this.genero = genero; }
public Date getFechaNacimiento() { return fechaNacimiento; }
public void setFechaNacimiento(Date fechaNacimiento) { this.fechaNacimiento = fechaNacimiento; }
@Override
public String toString() {
return "Usuario{" + "id=" + id + ", nombreUsuario='" + nombreUsuario + '\'' + ", edad=" + edad + '}';
}
}
Definición de Mapeos SQL
El archivo XML de mapeo contiene las sentencias SQL. El atributo namespace debe ser único y, idealmente, coincidir con la interfaz DAO si se utiliza programación orientada a interfaces.
<?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="mapeos.Usuario">
<select id="obtenerTodos" resultType="usuario">
SELECT id, nombre_usuario AS nombreUsuario, contrasena, edad, genero, fecha_nacimiento AS fechaNacimiento
FROM usuario
</select>
<select id="obtenerTodosComoMapa" resultType="map">
SELECT * FROM usuario
</select>
<select id="contarPorGenero" resultType="int" parameterType="map">
SELECT COUNT(*) FROM usuario WHERE genero = #{genero} AND edad >= #{edadMinima}
</select>
</mapper>
Pruebas de Integración
Para validar la configuración, se utiliza JUnit. El proceso implica cargar el archivo de configuración, construir la SqlSessionFactory y abrir una SqlSession para ejecutar las consultas.
package pruebas;
import modelo.Usuario;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertNotNull;
public class PruebaMapeoUsuario {
private SqlSessionFactory obtenerFactory() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis-core.xml");
return new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testObtenerEntidades() throws IOException {
try (SqlSession session = obtenerFactory().openSession()) {
List<Usuario> usuarios = session.selectList("mapeos.Usuario.obtenerTodos");
assertNotNull(usuarios);
usuarios.forEach(System.out::println);
}
}
@Test
public void testObtenerMapas() throws IOException {
try (SqlSession session = obtenerFactory().openSession()) {
List<Map<String, Object>> resultados = session.selectList("mapeos.Usuario.obtenerTodosComoMapa");
assertNotNull(resultados);
resultados.forEach(System.out::println);
}
}
@Test
public void testContarRegistros() throws IOException {
try (SqlSession session = obtenerFactory().openSession()) {
Map<String, Object> params = new HashMap<>();
params.put("genero", "M");
params.put("edadMinima", 18);
Integer total = session.selectOne("mapeos.Usuario.contarPorGenero", params);
System.out.println("Total de usuarios que cumplen el criterio: " + total);
}
}
}
Referencia de Nodos de Configuración
El archivo mybatis-core.xml requiere que los nodos hijos de <configuration> se declaren en un orden estricto, de lo contrario, el parser XML lanzará un error:
- properties: Importa variables desde archivos externos (
.properties). - settings: Ajusta el comportamiento en tiempo de ejecución de MyBatis (ej. caché, logs).
- typeAliases: Define nombres cortos para las clases Java, evitando usar el nombre completamente calificado en los mapeos. Se puede especificar por paquete.
- typeHandlers: Convierte tipos entre JDBC y Java.
- objectFactory: Permite personalizar la creación de instancias de los objetos de resultado.
- plugins: Intercepta llamadas a métodos de MyBatis para añadir funcionalidades como paginación.
- environments: Configura las conexiones a la base de datos, incluyendo el
transactionManagery eldataSource. - mappers: Define la ubicación de los archivos XML de mapeo SQL o las interfaces de mapeo.