MyBatis con interfaces para operaciones CRUD y consultas de relación uno a uno

Configuración del proyecto

Dependencias necesarias

Se rqeuiere agregar las librerías de MyBatis y el driver de la base de datos al proyecto.

Archivo de configuración principal

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <properties resource="database.properties"/>
    <typeAliases>
        <package name="com.entidades"/>
    </typeAliases>
    <environments default="desarrollo">
        <environment id="desarrollo">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${urlDB}"/>
                <property name="username" value="${usuario}"/>
                <property name="password" value="${clave}"/>
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <package name="com.interfaz"/>
    </mappers>
</configuration>

Propiedades de conexión

driver=oracle.jdbc.OracleDriver
urlDB=jdbc:oracle:thin:@localhost:1521:orcl
usuario=admin123
clave=secreto456

Definición de entidades

Clase Alumno

package com.entidades;

import java.io.Serializable;

public class Alumno implements Serializable {
    private Integer id;
    private String nombre;
    private String genero;
    private Integer grupo;
    
    public Alumno() {
    }

    public Alumno(Integer id, String nombre, String genero, Integer grupo) {
        this.id = id;
        this.nombre = nombre;
        this.genero = genero;
        this.grupo = grupo;
    }
    
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }

    public String getNombre() {
        return nombre;
    }
    
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
    
    public String getGenero() {
        return genero;
    }
    
    public void setGenero(String genero) {
        this.genero = genero;
    }

    public Integer getGrupo() {
        return grupo;
    }
    
    public void setGrupo(Integer grupo) {
        this.grupo = grupo;
    }

    @Override
    public String toString() {
        return "Alumno [id=" + id + ", nombre=" + nombre + ", genero=" + genero + ", grupo=" + grupo + "]";
    }
}

Clase Información del Alumno

package com.entidades;

import java.io.Serializable;
import java.util.Date;

public class InformacionAlumno implements Serializable {
    private Integer identificador;
    private Alumno alum;
    private String direccion;
    private Date fechaNacimiento;
    
    public InformacionAlumno() {
    }

    public InformacionAlumno(Integer identificador, Alumno alum, String direccion, Date fechaNacimiento) {
        this.identificador = identificador;
        this.alum = alum;
        this.direccion = direccion;
        this.fechaNacimiento = fechaNacimiento;
    }

    public Integer getIdentificador() {
        return identificador;
    }

    public void setIdentificador(Integer identificador) {
        this.identificador = identificador;
    }
    
    public Alumno getAlum() {
        return alum;
    }
    
    public void setAlum(Alumno alum) {
        this.alum = alum;
    }
    
    public String getDireccion() {
        return direccion;
    }
    
    public void setDireccion(String direccion) {
        this.direccion = direccion;
    }
    
    public Date getFechaNacimiento() {
        return fechaNacimiento;
    }
    
    public void setFechaNacimiento(Date fechaNacimiento) {
        this.fechaNacimiento = fechaNacimiento;
    }
    
    @Override
    public String toString() {
        return "InformacionAlumno [identificador=" + identificador + ", alum=" + alum + 
               ", direccion=" + direccion + ", fechaNacimiento=" + fechaNacimiento + "]";
    }
}

Interfaces de mapeo

Enterface AlumnoMapper

package com.interfaz;

import java.util.List;
import java.util.Map;
import com.entidades.Alumno;

public interface AlumnoMapper {
    /**
     * Insertar un nuevo registro
     */
    Integer insertar(Alumno entidad);
    
    /**
     * Eliminar un registro por identificador
     */
    Integer eliminar(Integer identificador);
    
    /**
     * Actualizar un registro existente
     */
    Integer actualizar(Alumno entidad);
    
    /**
     * Buscar por clave primaria
     */
    Alumno buscarPorId(Integer identificador);
    
    /**
     * Obtener todos los registros
     */
    List<Alumno> listarTodos();
    
    /**
     * Búsqueda con múltiples criterios
     */
    List<Alumno> buscarPorCriterios(Map<String, Object> parametros);
}

Interface InformacionAlumnoMapper

package com.interfaz;

import java.util.List;
import com.entidades.InformacionAlumno;

public interface InformacionAlumnoMapper {
    /**
     * Consulta con relación uno a uno
     * @return Lista de información de alumnos con datos relacionados
     */
    List<InformacionAlumno> listarTodos();
}

Archivos de mapeo XML

AlumnoMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<mapper namespace="com.interfaz.AlumnoMapper">
    <!-- Inserción de registro -->
    <insert id="insertar" parameterType="alumno">
        INSERT INTO alumnos VALUES(#{id},#{nombre},#{genero},#{grupo})    
    </insert> 
    
    <!-- Eliminación de registro -->
    <delete id="eliminar" parameterType="Integer">
        DELETE FROM alumnos a WHERE a.id=#{id} 
    </delete>
    
    <!-- Actualización de registro -->
    <update id="actualizar" parameterType="alumno">
        UPDATE alumnos a SET a.nombre=#{nombre},a.genero=#{genero},a.grupo=#{grupo} WHERE a.id=#{id}
    </update>
    
    <!-- Búsqueda por clave primaria -->
    <select id="buscarPorId" parameterType="Integer" resultType="alumno">
        SELECT * FROM alumnos a WHERE a.id=#{id} 
    </select>
    
    <!-- Listar todos los registros -->
    <select id="listarTodos" resultType="alumno">
        SELECT * FROM alumnos
    </select>
    
    <!-- Búsqueda con múltiples condiciones -->
    <select id="buscarPorCriterios" parameterType="Map" resultType="alumno">
        SELECT * FROM alumnos a WHERE a.id=#{id} AND a.nombre LIKE #{nombre}
    </select>
</mapper>

InformacionAlumnoMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<mapper namespace="com.interfaz.InformacionAlumnoMapper">
    <!-- Definición de resultado para relación uno a uno - primera aproximación -->
    <resultMap type="informacionAlumno" id="mapeoInfoCompleto">
        <result property="identificador" column="identificador"/>
        
        <result property="alum.id" column="id"/>
        <result property="alum.nombre" column="nombre"/>
        <result property="alum.genero" column="genero"/>
        <result property="alum.grupo" column="grupo"/>
        
        <result property="direccion" column="direccion"/>
        <result property="fechaNacimiento" column="fecha_nacimiento"/>
    </resultMap>
    
    <!-- Definición de resultado usando asociación - segunda aproximación -->
    <resultMap type="InformacionAlumno" id="mapeoConAsociacion">
        <association property="alum" column="id" select="com.interfaz.AlumnoMapper.buscarPorId"/>
    </resultMap>
    
    <select id="listarTodos" resultMap="mapeoConAsociacion">
        SELECT ia.identificador, ia.direccion, ia.fecha_nacimiento, a.id, a.nombre, a.genero, a.grupo 
        FROM info_alumnos ia
        INNER JOIN alumnos a ON ia.id_alumno=a.id
    </select>
</mapper>

Utilitario de SqlSession

package com.utilidades;

import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class GestorSqlSession {
    private static SqlSessionFactory fabricaSesiones;
    private static SqlSession sesion;
    
    public static SqlSessionFactory obtenerFabrica(){
        InputStream flujo=null;
        try {
            flujo = Resources.getResourceAsStream("mybatis-config.xml");
            fabricaSesiones = new SqlSessionFactoryBuilder().build(flujo);
            flujo.close();
        } catch (IOException excepcion) {
            excepcion.printStackTrace();
        }
        return fabricaSesiones;
    }
    
    public static SqlSession obtenerSesion(){
        sesion = obtenerFabrica().openSession();
        return sesion;
    }
    
    public static void main(String[] args) {
        System.out.println(obtenerSesion());
    }
}

Pruebas unitarias

Pruebas para operaciones CRUD

package com.utilidades;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.interfaz.AlumnoMapper;
import com.entidades.Alumno;

public class PruebaOperacionesCRUD {
    private SqlSession sesion;
    private AlumnoMapper mapeadorAlumno;
    
    @Before
    public void configurar() throws Exception {
        sesion = GestorSqlSession.obtenerSesion();
        mapeadorAlumno = sesion.getMapper(AlumnoMapper.class);
    }

    @After
    public void limpiar() throws Exception {
        sesion.commit();
        sesion.close();
    }

    @Test
    public void probarInsercion() {
        Alumno entidad = new Alumno(10, "Carlos", "M", 95201);
        int resultado = mapeadorAlumno.insertar(entidad);
        System.out.println("Registros afectados: " + resultado);
    }
    
    @Test
    public void probarEliminacion() {
        int resultado = mapeadorAlumno.eliminar(10);
        System.out.println("Registros eliminados: " + resultado);
    }
    
    @Test
    public void probarActualizacion() {
        Alumno entidad = new Alumno(100, "Laura", "F", 95203);
        int resultado = mapeadorAlumno.actualizar(entidad);
        System.out.println("Registros actualizados: " + resultado);
    }
    
    @Test
    public void probarBusquedaPorId() {
        Alumno entidad = mapeadorAlumno.buscarPorId(3);
        System.out.println(entidad);
    }
    
    @Test
    public void probarListarTodos() {
        List<Alumno> lista = mapeadorAlumno.listarTodos();
        for (Alumno elemento : lista) {
            System.out.println(elemento);
        }
    }
    
    @Test
    public void probarBusquedaConCriterios() {
        Map<String, Object> parametros = new HashMap<>();
        parametros.put("id", 100);
        parametros.put("nombre", "%Carlos%");
        List<Alumno> lista = mapeadorAlumno.buscarPorCriterios(parametros);
        for (Alumno elemento : lista) {
            System.out.println(elemento);
        }
    }
}

Pruebas para consulta con relación uno a uno

package com.utilidades;

import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.interfaz.InformacionAlumnoMapper;
import com.entidades.InformacionAlumno;

public class PruebaRelacionUnoAUno {
    private SqlSession sesion;
    private InformacionAlumnoMapper mapeadorInfo;
    
    @Before
    public void configurar() throws Exception {
        sesion = GestorSqlSession.obtenerSesion();
        mapeadorInfo = sesion.getMapper(InformacionAlumnoMapper.class);
    }

    @After
    public void limpiar() throws Exception {
        sesion.commit();
        sesion.close();
    }
    
    @Test
    public void probarConsultaRelacionada() {
        List<InformacionAlumno> lista = mapeadorInfo.listarTodos();
        for (InformacionAlumno elemento : lista) {
            System.out.println(elemento);
        }
    }
}

Resultados de búsqueda con múltiples condiciones

La consulta con múltiples criterios devuelve los registros que coinciden con los parámetros especificados en el mapa de entrada.

Publicado el 7-24 13:25