Integración de MyBatis con Spring Boot y Cache con Redis

0
7570

En este tutorial vamos a ver cómo integrar MyBatis con Spring Boot y como usar la caché de MyBatis sobre Redis.

0. Índice de contenidos

1. Introducción

El objetivo que perseguimos con el presente tutorial, es integrar el uso de MyBatis a través de los
starters de Spring Boot, ya que hasta hace poco, no disponíamos de un starter
dedicado a MyBatis y teníamos que configurarlo de la manera tradicional.

Posteriormente, veremos como usar la caché de segundo nivel que ofrece Mybatis con el soporte de Redis, tenéis más detalles del funcionamiento de la caché
de MyBatis en Caché MyBatis.

2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware: MacBook Pro 15' (2.3 GHz Intel Core i7, 16GB DDR3 SDRAM)
  • Sistema Operativo: Mac OS X El Capitan 10.11
  • Docker 1.11.1
  • Spring Boot 1.3.5
  • MyBatis 3.4.0
  • mybatis-spring-boot-starter 1.1.1
  • Redis 3.2.0
  • mybatis-redis-cache 1.0.0-beta2

3. Integrar MyBatis con Spring Boot

Como hemos comentado anteriormente Spring Boot no nos proporciona un starter dedicado a MyBatis y ha sido la gente de MyBatis la que ha desarrollado un starter con el que podemos
integrar y configurar facilmente este framework.

El primer paso que deberíamos realizar es incluir la dependencia en nuestro proyecto

    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>1.1.1</version>
    </dependency>
  

Como ya habéis podido ver en los diferentes tutoriales publicados sobre MyBatis los elementos fundamentales que hay que configurar para trabajar con MyBatis
son: SqlSessionFactoryBean, SqlSessionFactory, SqlSessionTemplate y los diferentes Mappers.

Repasemos lo que realiza mybatis-spring-boot-starter

  • Comprueba la existencia de un DataSource.
  • Crea una instancia de SqlSessionFactoryBean, pasandole como argumento el DataSource y que será la encargada de instanciar SqlSessionFactory
  • Crea una instancia del SqlSessionTemplate a través del SqlSessionFactory
  • Busca los Mappers dentro de nuestra aplicación, les asocia el SqlSessionTemplate y los registra para poder ser inyectados en nuestras clases de negocio.

Como en el resto de starters de Spring Boot podemos añadir una serie de parámetros de configuración dentro del fichero application.properties, usando el prefijo ‘mybatis’

  • mybatis.config-location: Localización del fichero mybatis-config.xml.
  • mapper-locations: Localización de los ficheros xml que representan a los ‘mappers’.
  • type-aliases-package: Paquete donde localizar los ‘alias’ de tipo.
  • type-handlers-package: Paquete donde localizar los ‘alias’ de los handlers.
  • executor-type: Tipo de ejecutor usado por MyBatis SIMPLE, REUSE, BATCH

Podéis ver los fuentes de este tutorial aquí, de todas formas vamos a repasar los aspectos más importantes:

Nuestro pom.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      	<modelVersion>4.0.0</modelVersion>

      	<groupId>com.autentia</groupId>
      	<artifactId>spring-boot-mybatis-demo</artifactId>
      	<version>0.0.1-SNAPSHOT</version>
      	<packaging>jar</packaging>

      	<name>spring-boot-mybatis-demo</name>
      	<description>Demo de la integracion de MyBatis con Spring Boot</description>

      	<parent>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-parent</artifactId>
      		<version>1.3.5.RELEASE</version>
      		<relativePath/>
      	</parent>

      	<properties>
      		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      		<java.version>1.8</java.version>
      	</properties>

      	<dependencies>
      		<!-- Starter MyBatis -->
      		<dependency>
      			<groupId>org.mybatis.spring.boot</groupId>
      			<artifactId>mybatis-spring-boot-starter</artifactId>
      			<version>1.1.1</version>
      		</dependency>
              <!-- H2 BBDD -->
      		<dependency>
      			<groupId>com.h2database</groupId>
      			<artifactId>h2</artifactId>
      			<scope>runtime</scope>
      		</dependency>
              <!-- Test-->
      		<dependency>
      			<groupId>org.springframework.boot</groupId>
      			<artifactId>spring-boot-starter-test</artifactId>
      			<scope>test</scope>
      		</dependency>
      		<dependency>
      			<groupId>org.hamcrest</groupId>
      			<artifactId>hamcrest-all</artifactId>
      			<version>1.3</version>
      		</dependency>
      		<dependency>
      			<groupId>junit</groupId>
      			<artifactId>junit</artifactId>
      		</dependency>
      	</dependencies>

      	<build>
      		<plugins>
      			<plugin>
      				<groupId>org.springframework.boot</groupId>
      				<artifactId>spring-boot-maven-plugin</artifactId>
      			</plugin>
      		</plugins>
      	</build>

      </project>

  

A parte de la dependencia con mybatis-spring-boot-starter, destacamos la dependencia con H2 para crear una BBDD en memoria sobre la que lanzaremos nuestros Test de Integraci&oacuten. Esta BBDD se creará a partir de un fichero *.sql que le indicaremos en el application.properties

Dentro del directorio src/main/resources vamos a incluir el fichero de propiedades application.properties que tendrá el siguiente aspecto:

# Script de Inicialización de BBDD
spring.datasource.schema=schema.sql

#Fichero de Configuración de MyBatis
mybatis.config-location=mybatis-config.xml

# Configuración de Logs
logging.level.root=WARN
logging.level.com.autentia.mappers=TRACE
    

El parámetro spring.datasource.schema indica el fichero .sql utilizado para crear y poblar la BBDD.

mybatis.config-location como hemos visto anteriormente indica la ubicación del fichero de configuración de MyBatis.

logging.level.root y logging.level.com.autentia.mappers indican el nivel de traza.

El fichero de configuración de MyBatis (mybatis-config.xml)

  <?xml version="1.0" encoding="UTF-8" ?>
  <!DOCTYPE configuration
          PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
          "http://mybatis.org/dtd/mybatis-3-config.dtd">
  <configuration>
      <typeAliases>
          <package name="com.autentia.model"/>
      </typeAliases>
      <mappers>
          <mapper resource="com/autentia/mappers/CourseMapper.xml"/>
      </mappers>
  </configuration>

Como se puede observar, hemos declarado el fichero xml que define un mapper CourseMapper.xml y un paquete com.autentia.model que se utilizará para
localizar los alias de tipo que usaremos en los mappers.

Vamos a ver el contenido de schema.sql

    -- Create Table
    create table courses (name varchar, credits int);

    -- Insert data
    insert into courses (name, credits) values ('Angular 2', 1);
    insert into courses (name, credits) values ('PrimeFaces', 2);
  

Este script no presenta mucha complicación simplemente crea una tabla ‘Courses’ y la puebla con 2 registros. Ahora sólo nos falta crear
la infraestructura relativa a los ‘mappers’, en primer lugar creamos la interfaz CourseMapper en la que definimos nuestros métodos de acceso a BBDD:

@Mapper
public interface CourseMapper {

    List getCourses();
}

  

y el fichero asociado CourseMapper.xml

    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

    <mapper namespace="com.autentia.mappers.CourseMapper">

        <select id="getCourses" resultType="Course">
            select * from courses
        </select>

    </mapper>
  

En este fichero vincularemos el método getCourses definido en la interfaz con la query select * from courses para devolver objetos de tipo Course.

Para probar el correcto funcionamiento creamos un test de integración CourseMapperIntegrationTest con el siguiente contenido:

      @RunWith(SpringJUnit4ClassRunner.class)
      @SpringApplicationConfiguration(classes = SpringBootMyBatisIntegrationDemo.class)
      public class CourseMapperIntegrationTest {

          @Autowired
          private CourseMapper courseMapper;

          @Test
          public void getCourses() throws Exception {
              List courses = courseMapper.getCourses();
              MatcherAssert.assertThat(courses, hasSize(2));
          }

      }
    

El test comprueba que existen 2 cursos en nuestra BBDD, lo lanzamos desde nuestro IDE y debería pasar sin problemas

01_spring_boot-mybatis

Sencillo no???

4. Uso de la caché de MyBatis con Redis

En este apartado vamos a ver como podemos activar la caché de segundo nivel de MyBatis para que use como soporte Redis (todos los detalles sobre la caché
de MyBatis en el tutorial de mi compañero
Jose Luis Caché MyBatis) .

El primer paso es añadir la siguiente dependencia a nuestro pom.xml

    <!-- Mybatis Redis Cache -->
    <dependency>
      <groupId>org.mybatis.caches</groupId>
      <artifactId>mybatis-redis</artifactId>
      <version>1.0.0-beta2</version>
    </dependency>
  

El siguiente paso es añadir el soporte de caché a nivel de mapper para que use redis, para ello incluimos lo siguiente en nuestro CourseMapper.xml

    <cache type="org.mybatis.caches.redis.RedisCache"/>
  

Por último creamos el fichero de configuración en el que especificamos la url y puerto de nuestro servidor de Redis

host=192.168.99.100
port=6379

Pero, falta algo no ??? Efectivamente nos falta un servidor de Redis y como siempre Docker aparece al rescate ;).

  docker run -d --name redis_cache -p 6379:6379 redis

Este comando levanta un contenedor con redis y expone el puerto 6379 para que podamos acceder a él. Entramos en el contenedor ejecutando lo siguiente:

  docker exec -it redis_cache bash

Una vez dentro del contenedor redis, ejecutamos el cliente redis-cli y ejecutamos monitor para activar el monitor de redis, y poder ver las operaciones que se realicen contra él.

02_spring_boot_redis_cache

Lanzamos la prueba de nuevo y observamos lo que ocurre en el monitor de redis:

03_spring_boot_redis_cache

Como podemos observar por el monitor, se han realizado 2 operaciones: la primera HGET para ver si la consulta estaba cacheada
en redis y posteriormente una HSET para insertar los valores devueltos por la consulta a BBDD.

Volvemos a ejecutar la consulta:

04_spring_boot_redis_cache

Como podemos comprobar, se ha realizado únicamente una operación HGET para recuperar los valores de la caché, sin necesidad de acceder a la BBDD. Lo vemos más
claro en los logs que presenta nuestro IDE, en esta ejecución no aparecen los logs relativos a la consulta realizada con MyBatis

05_spring_boot_redis_cache

5. Conclusiones

Como hemos podido comprobar, Spring Boot, a través de los starters nos facilita enormemente la creación y configuración
de un nuestras aplicaciones, dejándonos más tiempo para centrarnos en las funcionalidades de negocio.

Por otro lado hemos visto lo fácil que resulta la activación de la caché de segundo nivel de MyBatis con el soporte de Redis, esta librería está en versión 1.0.0-beta2
y aún le falta el soporte para RedisCluster, pero por lo que hemos estado viendo en su repo están en ello.

Un saludo.

6. Referencias

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad