lunes, 10 de marzo de 2014

Empezando con Mybatis, Netbeans y MySQL

MyBatis es un framework de persistencia de Java que permite el acceso a base de datos mediante la ejecución de comandos DML evitando que el programador escriba todo el código manualmente, tal como se hacía con JDBC.
En este artículo les mostraré la manera de cómo utilizar Mybatis en nuestros proyectos de Netbeans (la configuración en Eclipse o JDeveloper es la misma) utilizando una base de datos MySQL. La imagen que se muestra a continuación representa el árbol de paquetes que va a estructurar a nuestro proyecto.

Fig 1. Estructura de paquetes del proyecto de ejemplo
Esencialmente, para poder utilizar Mybatis debemos agregar la librería del framework que podemos descargar de su página y además debemos agregar un archivo de configuración llamado mybatis-config.xml. En este archivo se encuentran los parámetros de conexión a la base de datos así como también los mappers, que son elementos que se encargan de indicarle a Mybatis dónde encontrar las sentencias SQL mapeadas.
<?xml version="1.0" encoding="UTF-8"?>

<!--
    Document   : mybatis-config.xml
    Created on : 9 de marzo de 2014, 20:51
    Author     : Rolando
    Description:
        Purpose of the document follows.
-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="configuracion.properties"/>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/rolandopalermo/example/data/TbVehiculos.xml"/>
    </mappers>
</configuration>
Como podemos notar, los parámetros de conexión no están establecidos explícitamente en la sección correspondiente sino que son leídos de un archivo de propiedades. Para esto, debemos indicarle a Mybatis la ruta de este archivo properties agregando una propiedad en nuestra configuración: <properties resource="configuracion.properties"/>. El archivo properties es el que se muestra a continuación:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/rolandopalermo
username=root
password=admin
Hecho esto, ahora procedemos a crear el POJO que se encargará de mapear un objeto Java con la tabla sobre la que queremos hacer un mantenimiento. Obviamente, antes de eso, debemos crear la base de datos utilizando el script siguiente:
-- MySQL Administrator dump 1.4
--
-- ------------------------------------------------------
-- Server version 5.5.16


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;


--
-- Create schema rolandopalermo
--

CREATE DATABASE IF NOT EXISTS rolandopalermo;
USE rolandopalermo;

--
-- Definition of table `tb_mantenimiento`
--

DROP TABLE IF EXISTS `tb_mantenimiento`;
CREATE TABLE `tb_mantenimiento` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `id_vehiculo` int(10) unsigned NOT NULL,
  `fecha_mantenimiento` date NOT NULL,
  `id_piloto` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_tb_mantenimiento_vehiculo` (`id_vehiculo`),
  KEY `FK_tb_mantenimiento_piloto` (`id_piloto`),
  CONSTRAINT `FK_tb_mantenimiento_piloto` FOREIGN KEY (`id_piloto`) REFERENCES `tb_piloto` (`id`),
  CONSTRAINT `FK_tb_mantenimiento_vehiculo` FOREIGN KEY (`id_vehiculo`) REFERENCES `tb_vehiculos` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

--
-- Dumping data for table `tb_mantenimiento`
--

/*!40000 ALTER TABLE `tb_mantenimiento` DISABLE KEYS */;
INSERT INTO `tb_mantenimiento` (`id`,`id_vehiculo`,`fecha_mantenimiento`,`id_piloto`) VALUES 
 (1,1,'2013-11-17',1),
 (2,2,'2013-11-14',2),
 (3,3,'2013-11-17',3),
 (4,4,'2013-09-12',3),
 (5,5,'2013-11-17',2),
 (6,5,'2013-11-17',2),
 (7,6,'2013-11-17',1),
 (8,6,'2013-09-29',1),
 (9,2,'2013-11-17',2);
/*!40000 ALTER TABLE `tb_mantenimiento` ENABLE KEYS */;


--
-- Definition of table `tb_modelo`
--

DROP TABLE IF EXISTS `tb_modelo`;
CREATE TABLE `tb_modelo` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `descripcion` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

--
-- Dumping data for table `tb_modelo`
--

/*!40000 ALTER TABLE `tb_modelo` DISABLE KEYS */;
INSERT INTO `tb_modelo` (`id`,`descripcion`) VALUES 
 (1,'SCANIA 3 EJES'),
 (2,'CABEZAL VOLVO'),
 (3,'CARRETA 4 EJES');
/*!40000 ALTER TABLE `tb_modelo` ENABLE KEYS */;


--
-- Definition of table `tb_piloto`
--

DROP TABLE IF EXISTS `tb_piloto`;
CREATE TABLE `tb_piloto` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `nombre` varchar(60) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

--
-- Dumping data for table `tb_piloto`
--

/*!40000 ALTER TABLE `tb_piloto` DISABLE KEYS */;
INSERT INTO `tb_piloto` (`id`,`nombre`) VALUES 
 (1,'Juan Pérez'),
 (2,'José Guzmán'),
 (3,'Luis Díaz'),
 (4,'Pedro Suarez'),
 (5,'Arturo Pomar');
/*!40000 ALTER TABLE `tb_piloto` ENABLE KEYS */;


--
-- Definition of table `tb_vehiculos`
--

DROP TABLE IF EXISTS `tb_vehiculos`;
CREATE TABLE `tb_vehiculos` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `numero_placa` varchar(45) NOT NULL,
  `fecha_registro` date NOT NULL,
  `id_modelo` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_tb_vehiculos_modelos` (`id_modelo`),
  CONSTRAINT `FK_tb_vehiculos_modelos` FOREIGN KEY (`id_modelo`) REFERENCES `tb_modelo` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;

--
-- Dumping data for table `tb_vehiculos`
--

/*!40000 ALTER TABLE `tb_vehiculos` DISABLE KEYS */;
INSERT INTO `tb_vehiculos` (`id`,`numero_placa`,`fecha_registro`,`id_modelo`) VALUES 
 (1,'SD-3456','2013-11-17',1),
 (2,'XS-9843','2013-11-17',2),
 (3,'LM-5621','2013-11-17',3),
 (4,'GB-0045','2013-11-17',2),
 (5,'KN-2354','2013-11-17',1),
 (6,'YL-5625','2013-11-17',2),
 (8,'XD-1237','2014-09-03',3),
 (9,'XD-1237','2014-09-03',3),
 (10,'XD-1237','2014-09-03',3),
 (11,'XD-1237','2014-09-03',3);
/*!40000 ALTER TABLE `tb_vehiculos` ENABLE KEYS */;




/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
Ahora vamos a crear un mantenimiento a la tabla rolandopalermo.tb_vehiculos, por lo que debemos crear un POJO que haga un mapeo de cada columna de dicha tabla.
Fig 2. Tabla sobre la que se hará el mantenimiento
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rolandopalermo.example.model;

/**
 *
 * @author Rolando
 */
public class TbVehiculos {

    private String id;
    private String numeroPlaca;
    private String fechaRegistro;
    private String idModelo;

    public String getFechaRegistro() {
        return fechaRegistro;
    }

    public void setFechaRegistro(String fechaRegistro) {
        this.fechaRegistro = fechaRegistro;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getIdModelo() {
        return idModelo;
    }

    public void setIdModelo(String idModelo) {
        this.idModelo = idModelo;
    }

    public String getNumeroPlaca() {
        return numeroPlaca;
    }

    public void setNumeroPlaca(String numeroPlaca) {
        this.numeroPlaca = numeroPlaca;
    }
}
Ahora hay que crear el archivo de mapeo TbVehiculos.xml para que Mybatis puede interpretar que la clase TbVehiculos hace referencia a la tabla tb_vehiculos y también la manera en que los atributos se relacionan con las columnas.
<?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="TbVehiculos">
 
    <resultMap id="result" type="com.rolandopalermo.example.model.TbVehiculos">
        <result property="id" column="ID"/>
        <result property="numeroPlaca" column="NUMERO_PLACA"/>
        <result property="fechaRegistro" column="FECHA_REGISTRO"/>
        <result property="idModelo" column="ID_MODELO"/>
    </resultMap>
 
    <select id="getAll" resultMap="result">
        SELECT * FROM TB_VEHICULOS
    </select>
 
    <select id="getById" parameterType="int" resultMap="result">
        SELECT * FROM TB_VEHICULOS WHERE ID = #{id}
    </select>
 
    <delete id="deleteById" parameterType="int">
        DELETE from TB_VEHICULOS WHERE ID = #{id};
    </delete>
 
    <insert id="insert" parameterType="com.rolandopalermo.example.model.TbVehiculos">
    INSERT INTO TB_VEHICULOS (NUMERO_PLACA, FECHA_REGISTRO, ID_MODELO)
        VALUES (#{numeroPlaca}, #{fechaRegistro}, #{idModelo});
    </insert>
 
    <update id="update" parameterType="com.rolandopalermo.example.model.TbVehiculos">
        UPDATE TB_VEHICULOS
        SET
            NUMERO_PLACA = #{numeroPlaca},
            FECHA_REGISTRO = #{fechaRegistro},
            ID_MODELO = #{idModelo}
        WHERE ID = #{id};
    </update>
 
</mapper>
Ahora hay que indicarle a Mybatis de dónde debe leer los parámetros de conexión para poder crear las sesiones. Para esto creamos la clase MyBatisConnectionFactory.
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rolandopalermo.example.dao;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
 *
 * @author Rolando
 */
public class MyBatisConnectionFactory {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {

            String resource = "mybatis-config.xml";
            Reader reader = Resources.getResourceAsReader(resource);

            if (sqlSessionFactory == null) {
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            }
        } catch (FileNotFoundException fileNotFoundException) {
            fileNotFoundException.printStackTrace();
        } catch (IOException iOException) {
            iOException.printStackTrace();
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {

        return sqlSessionFactory;
    }
}
Y ahora creamos la clase DAO, quien a través de sus métodos encapsulará las operaciones que vamos a realizar sobre la tabla tb_vehiculos.
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rolandopalermo.example.dao;

import com.rolandopalermo.example.model.TbVehiculos;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

/**
 *
 * @author Rolando
 */
public class TbVehiculosDAO {

    private SqlSessionFactory sqlSessionFactory;

    public TbVehiculosDAO() {
        sqlSessionFactory = MyBatisConnectionFactory.getSqlSessionFactory();
    }

    @SuppressWarnings("unchecked")
    public List<TbVehiculos> selectAll() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            List<TbVehiculos> list = session.selectList("TbVehiculos.getAll");
            return list;
        } finally {
            session.close();
        }
    }

    public TbVehiculos selectById(int id) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            TbVehiculos contact = (TbVehiculos) session.selectOne("TbVehiculos.getById", id);
            return contact;
        } finally {
            session.close();
        }
    }

    public void update(TbVehiculos contact) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            session.update("TbVehiculos.update", contact);
            session.commit();
        } finally {
            session.close();
        }
    }

    public void insert(TbVehiculos contact) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            session.insert("TbVehiculos.insert", contact);
            session.commit();
        } finally {
            session.close();
        }
    }

    public void delete(int id) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            session.delete("TbVehiculos.deleteById", id);
            session.commit();
        } finally {
            session.close();
        }
    }
}
Y por último la clase de prueba que nos permitirá saber si toda nuestra configuración fue hecha correctamente.
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rolandopalermo.example.test;

import com.rolandopalermo.example.dao.TbVehiculosDAO;
import com.rolandopalermo.example.model.TbVehiculos;
import java.util.List;

/**
 *
 * @author Rolando
 */
public class Main {

    public static void main(String[] args) {
        TbVehiculosDAO dao = new TbVehiculosDAO();
        List<TbVehiculos> lstVehiculos = dao.selectAll();
        for (TbVehiculos tbVehiculos : lstVehiculos) {
            System.out.println(tbVehiculos.getId() + "t" + tbVehiculos.getNumeroPlaca());
        }
        TbVehiculos nuevoVehiculo = new TbVehiculos();
        nuevoVehiculo.setFechaRegistro("2014-03-10");
        nuevoVehiculo.setIdModelo("1");
        nuevoVehiculo.setNumeroPlaca("Test");
        dao.insert(nuevoVehiculo);
        System.out.println("--------------------");
        lstVehiculos = dao.selectAll();
        for (TbVehiculos tbVehiculos : lstVehiculos) {
            System.out.println(tbVehiculos.getId() + "t" + tbVehiculos.getNumeroPlaca());
        }
    }
}
Y el resultado:

Aquí les adjunto el enlace para poder descargar el proyecto:
Y en un siguiente artículo les mostraré cómo invocar a un procedimiento almacenado desde Mybatis. Saludos y hasta una próxima oportunidad.

3 comentarios:

luis sanchez dijo...

Excelente articulo. Muchas Gracias

Anónimo dijo...

como se haría el mapeo con vistas o con joins

vianey vargas dijo...

Excelente tutorial , Quisiera saber para llamar un procedimiento almacenado mysql desde mybatis con parametros de entrada y salida .muchas gracias.


CALL sp_InsertCity(
#{codCity},
#{nameCity},
#{respuesta,jdbcType=VARCHAR,javaType=java.lang.String, mode=OUT})

Publicar un comentario