Integrar MyBatis a Spring Framework

Anteriormente mostramos el uso del Framework MyBatis para agilizar el desarrollo de aplicaciones con acceso a datos, ahora nos centraremos en la integración de MyBatis a Spring, aprenderemos los pasos necesarios para integrar esta tecnología al contenedor IoC de Spring, la integración admite manejo de transacciones, transformación de excepciones, y todo lo requerido para el funcionamiento de ambas bibliotecas.

Para integrar estos frameworks requerimos añadir las siguientes dependencias:

<!-- Integrar MyBatis y Spring -->
 <dependency>
     <groupId>org.mybatis</groupId>
     <artifactId>mybatis-spring</artifactId>
     <version>1.3.0</version>
 </dependency>
 
 <!-- Libs Spring requeridas -->
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>4.3.8.RELEASE</version>
 </dependency>
 
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-jdbc</artifactId>
     <version>4.3.8.RELEASE</version>
 </dependency>
 
 <!-- Lib MyBatis requerida -->
 <dependency>
     <groupId>org.mybatis</groupId>
     <artifactId>mybatis</artifactId>
     <version>3.4.4</version>
 </dependency>
 
 <!-- Driver HSQLDB -->
 <dependency>
     <groupId>org.hsqldb</groupId>
     <artifactId>hsqldb</artifactId>
     <version>2.4.0</version>
 </dependency>

Una vez tenemos las dependencias necesarias para nuestro proyecto podemos ir a la configuración de acceso a datos, para ello creamos la clase AppConfig y usaremos la anotación @Configuration para configurar desde código Java.

@Configuration
@MapperScan("tutor.java.mybatisexample.data")
public class AppConfig {

    @Bean
    public DataSource dataSource() {
        
        //return new EmbeddedDatabaseBuilder().addScript("schema.sql").build()
        
        PooledDataSource pds = new PooledDataSource();
        pds.setDriver("org.hsqldb.jdbcDriver");
        pds.setUrl("jdbc:hsqldb:hsql://localhost/");
        pds.setUsername("SA");
        pds.setPassword("");
        
        return pds;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        return sessionFactory.getObject();
    }
}

Lo primero que hacemos es crear el DataSource podemos usar la clase PooledDataSource que usamos el el tutorial MyBatis o EmbeddedDataSource de Spring para conectarnos a una de las bases de datos embebidas soportadas, puedes cambiar los datos de conexión para usar otra base de datos, solo recuerda agregar el driver correspondiente.

Luego creamos el bean SqlSessionFactory encargado de crear las sesiones para las consultas de los datos.

Si vemos la clase podremos apreciar la anotación @MapperScan usaremos la misma para ubicar las interfaces de mapeo requeridas por el Framework MyBatis, debemos indicar el paquete en donde se encuentran las mismas, para cada una de estas interfaces se creará el respectivo Spring bean.

package tutor.java.mybatisexample.data;

import java.util.List;
import org.apache.ibatis.annotations.Select;

public interface CustomerMapper {

    @Select("SELECT * FROM Customer WHERE id = #{id}")
    Customer selectCustomerById(long id);
    
    @Select("SELECT * FROM Customer")
    List<Customer> selectAllCustomer();
    
}

Esta es nuestra clase de mapeo, la misma que usamos en el tutorial previo, esta utiliza el siguiente modelo de datos:

public class Customer {

    private Long id;
    private String firstname;
    private String lastname;
    private String street;
    private String city;

    // ...
}

Ya tenemos todo preparado para iniciar el contexto Spring, como hemos usado anotaciones para la configuración debemos usar la clase AnnotationConfigApplicationContext luego podremos usar el método getBean() para obtener la clase de mapeo y consultar los datos.

public class MyBatisSpringExample {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext ctx
                = new AnnotationConfigApplicationContext(AppConfig.class);

        CustomerMapper cm = ctx.getBean(CustomerMapper.class);
        cm.selectAllCustomer().forEach(System.out::println);
    }
}

Al ejecutar obtenemos el siguiente resultado:

Customer{id=0, firstname=Laura, lastname=Steel, street=429 Seventh Av., city=Dallas}
Customer{id=1, firstname=Robert, lastname=King, street=267 - 20th Ave., city=Seattle}
Customer{id=2, firstname=Robert, lastname=Sommer, street=22 - 20th Ave., city=Oslo}
Customer{id=3, firstname=Michael, lastname=Smith, street=455 Upland Pl., city=Lyon}
Customer{id=4, firstname=Bill, lastname=Fuller, street=363 Seventh Av., city=Oslo}
//...

Podemos inyectar los mapper como cualquier otro bean, por ejemplo, usaremos @Autowired para inyectarlo en una clase de la capa de servicios:

@Service
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    private CustomerMapper mapper;

    @Override
    public List<Customer> findAll() {
        return mapper.selectAllCustomer();
    }

    @Override
    public Customer findOne(Long id) {
        return mapper.selectCustomerById(id);
    }
}

Para utilizar este componente de la capa de servicios hacemos lo siguiente:

ctx.scan("tutor.java.mybatisexample.service");

CustomerService cs = ctx.getBean(CustomerService.class);
cs.findAll().forEach(System.out::println);

El código ctx.scan("...") nos sirve para indicar a Spring que debe escanear el paquete indicado en busca de componentes, esto pudimos haberlo hecho anotando la clase AppConfig con @ConponentScan("...") e indicando el paquete respectivo.

En esta demostración hemos realizado la configuración sin utilizar XML pero debemos saber que podemos utilizarlo si lo deseamos, ya sea para uno o ambos frameworks.

Descargar proyecto: integrar-spring-mybatis.zip

Comentarios

Temas relacionados

Entradas populares de este blog

Conectar SQL Server con Java

Entrenar OpenCV en Detección de Objetos

Manipular pixeles OpenCV Python

Detección de contornos con OpenCV Python

Conociendo la clase cv::Mat de OpenCV