Mapeo de Relaciones Uno a Muchos y Muchos a Muchos en Mybatis

En Mybatis, las relaciones de asociación entre tablas de bases de datos se configuran mediante archivos XML y clases Java, permitiendo mapear entidades relacionadas de forma eficiente.

Relación Uno a Muchos: Pedido y Detalles de Pedido

Para demostrar una relación uno a muchos, se utilizan tablas de ejemplo: una tabla de pedidos y otra de detalles de pedido. Se crean clases de representación (VO) para incluir las colecciones anidadas.

Clase de representación para Pedido (PedidoRep.java):

package com.ejemplo.modelo;
import java.util.ArrayList;
import java.util.List;

public class PedidoRep extends Pedido {
    private List<DetallePedido> detalles = new ArrayList<>();

    public List<DetallePedido> getDetalles() {
        return detalles;
    }

    public void setDetalles(List<DetallePedido> detalles) {
        this.detalles = detalles;
    }
}

Clase de representación para Detalle de Pedido (DetallePedidoRep.java):

package com.ejemplo.modelo;

public class DetallePedidoRep extends DetallePedido {
    private Pedido pedido;

    public Pedido getPedido() {
        return pedido;
    }

    public void setPedido(Pedido pedido) {
        this.pedido = pedido;
    }
}

Interfaz del mapper para Pedido (PedidoMapper.java):

package com.ejemplo.mapper;
import com.ejemplo.modelo.PedidoRep;
import org.apache.ibatis.annotations.Param;

public interface PedidoMapper {
    PedidoRep obtenerPedidoConDetalles(@Param("idPedido") Integer idPedido);
}

Configuración XML para mapeo uno a muchos (PedidoMapper.xml):

<resultMap id="PedidoRepMap" type="com.ejemplo.modelo.PedidoRep">
    <result property="idPedido" column="id_pedido"/>
    <result property="numeroPedido" column="numero_pedido"/>
    <collection property="detalles" ofType="com.ejemplo.modelo.DetallePedido">
        <result property="idDetalle" column="id_detalle"/>
        <result property="idProducto" column="id_producto"/>
        <result property="cantidad" column="cantidad"/>
        <result property="fkPedido" column="fk_pedido"/>
    </collection>
</resultMap>

<select id="obtenerPedidoConDetalles" resultMap="PedidoRepMap" parameterType="java.lang.Integer">
    SELECT p.id_pedido, p.numero_pedido, d.id_detalle, d.id_producto, d.cantidad, d.fk_pedido
    FROM tabla_pedido p INNER JOIN tabla_detalle_pedido d ON p.id_pedido = d.fk_pedido
    WHERE p.id_pedido = #{idPedido}
</select>

Para la relación muchos a uno, se invierte el enfoque. Interfaz del mapper para DetallePedido (DetallePedidoMapper.java):

package com.ejemplo.mapper;
import com.ejemplo.modelo.DetallePedidoRep;
import org.apache.ibatis.annotations.Param;

public interface DetallePedidoMapper {
    DetallePedidoRep obtenerDetalleConPedido(@Param("idDetalle") Integer idDetalle);
}

Configuración XML para mapeo muchos a uno (DetallePedidoMapper.xml):

<resultMap id="DetallePedidoRepMap" type="com.ejemplo.modelo.DetallePedidoRep">
    <result property="idDetalle" column="id_detalle"/>
    <result property="idProducto" column="id_producto"/>
    <result property="cantidad" column="cantidad"/>
    <result property="fkPedido" column="fk_pedido"/>
    <association property="pedido" javaType="com.ejemplo.modelo.Pedido">
        <result property="idPedido" column="id_pedido"/>
        <result property="numeroPedido" column="numero_pedido"/>
    </association>
</resultMap>

<select id="obtenerDetalleConPedido" resultMap="DetallePedidoRepMap" parameterType="java.lang.Integer">
    SELECT p.id_pedido, p.numero_pedido, d.id_detalle, d.id_producto, d.cantidad, d.fk_pedido
    FROM tabla_pedido p INNER JOIN tabla_detalle_pedido d ON p.id_pedido = d.fk_pedido
    WHERE d.id_detalle = #{idDetalle}
</select>

Relación Muchos a Muchos: Libros y Categorías

Para relaciones muchos a muchos, se usa una tabla intermedia. Ejemplo con libros y categorías.

Clase de representación para Libro (LibroRep.java):

package com.ejemplo.modelo;
import java.util.ArrayList;
import java.util.List;

public class LibroRep extends Libro {
    private List<Categoria> categorias = new ArrayList<>();

    public List<Categoria> getCategorias() {
        return categorias;
    }

    public void setCategorias(List<Categoria> categorias) {
        this.categorias = categorias;
    }
}

Clase de representación para Categoria (CategoriaRep.java):

package com.ejemplo.modelo;
import java.util.ArrayList;
import java.util.List;

public class CategoriaRep extends Categoria {
    private List<Libro> libros = new ArrayList<>();

    public List<Libro> getLibros() {
        return libros;
    }

    public void setLibros(List<Libro> libros) {
        this.libros = libros;
    }
}

Interfaz del mapper para la tabla intermedia (LibroCategoriaMapper.java):

package com.ejemplo.mapper;
import com.ejemplo.modelo.CategoriaRep;
import com.ejemplo.modelo.LibroRep;
import org.apache.ibatis.annotations.Param;

public interface LibroCategoriaMapper {
    LibroRep buscarLibroConCategorias(@Param("idLibro") Integer idLibro);
    CategoriaRep buscarCategoriaConLibros(@Param("idCategoria") Integer idCategoria);
}

Configuración XML para mapeos muchos a muchos (LibroCategoriaMapper.xml):

<resultMap id="LibroRepMap" type="com.ejemplo.modelo.LibroRep">
    <result property="idLibro" column="id_libro"/>
    <result property="titulo" column="titulo"/>
    <result property="precio" column="precio"/>
    <collection property="categorias" ofType="com.ejemplo.modelo.Categoria">
        <result property="idCategoria" column="id_categoria"/>
        <result property="nombreCategoria" column="nombre_categoria"/>
    </collection>
</resultMap>

<resultMap id="CategoriaRepMap" type="com.ejemplo.modelo.CategoriaRep">
    <result property="idCategoria" column="id_categoria"/>
    <result property="nombreCategoria" column="nombre_categoria"/>
    <collection property="libros" ofType="com.ejemplo.modelo.Libro">
        <result property="idLibro" column="id_libro"/>
        <result property="titulo" column="titulo"/>
        <result property="precio" column="precio"/>
    </collection>
</resultMap>

<select id="buscarLibroConCategorias" resultMap="LibroRepMap" parameterType="java.lang.Integer">
    SELECT l.id_libro, l.titulo, l.precio, c.id_categoria, c.nombre_categoria
    FROM tabla_libro l
    INNER JOIN tabla_libro_categoria lc ON l.id_libro = lc.fk_libro
    INNER JOIN tabla_categoria c ON lc.fk_categoria = c.id_categoria
    WHERE l.id_libro = #{idLibro}
</select>

<select id="buscarCategoriaConLibros" resultMap="CategoriaRepMap" parameterType="java.lang.Integer">
    SELECT c.id_categoria, c.nombre_categoria, l.id_libro, l.titulo, l.precio
    FROM tabla_categoria c
    INNER JOIN tabla_libro_categoria lc ON c.id_categoria = lc.fk_categoria
    INNER JOIN tabla_libro l ON lc.fk_libro = l.id_libro
    WHERE c.id_categoria = #{idCategoria}
</select>

Estos ejemplos ilustran cómo configurar relaciones uno a muchos y muchos a muchos en Mybatis, adaptando las clases VO y configuraciones XML para reflejar las asociaciones necesarias.

Etiquetas: MyBatis java SQL ORM Uno a Muchos

Publicado el 6-8 23:39