lunes
may242010
MyBatis 3 + Spring 3.1 para los que les gusta el SQL
lunes, mayo 24, 2010 at 11:05PM
Introducción a MyBatis 3
Se ha publicado la última versión del framework de persistencia MyBatis (antiguamente conocido como iBATIS).Para los que no lo conozcan MyBatis es una utilidad que ejecuta sentencias SQL y mapea sus resultados a POJOs.
Los dos puntos fuertes de MyBatis son su simplicidad y su infinita flexibilidad que permite usar cualquier base de datos por mal hecha que esté sin demasiados problemas.
A diferencia de JPA, Hibernate o Cayenne, MyBatis no pretende mapear un modelo relacional a un modelo de objetos. No es necesario describir las relaciones de las tablas en ficheros XML ni utilizar dialectos del SQL para solucionar relaciones imposibles.
Mappers y Fichero XML de sentencias
Básicamente MyBatis consiste en definir un fichero de sentencias SQL como este:<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="org.example.UserMapper">
<select id="getUser" resultType="org.example.User" parameterType="org.example.User">
select * from users where id=#{id} and name=#{name}
</select>
</mapper>
Este fichero indica que existe un método llamado getUser en un objeto (aka mapper) llamado org.example.UserMapper. Indica también que cuando se ejecute getUser se espera recibir como parametro de entrada un pojo org.example.User y que se devolverá otro pojo org.example.User
Un mapper es un DAO, es decir, un objeto de acceso a datos. Con MyBatis no es necesario construir una implementación, basta con definir la interfaz. MyBatis genera un proxy dinámico con la implementación.
En nuestro caso el UserMapper es simplemente:
public interface UserMapper {
User getUser(User user);
}
API de MyBatis
MyBatis dispone de un API muy sencillo para obtener le mapper y ejecutar la sentencia. Básicamente consiste en esto:SqlSession session = sessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
return userMapper.getUser();
Sin embargo, y aunque este código es bastante sencillo no es código de negocio sino código técnico que no aporta gran cosa, sencillamente hay que escribirlo o el programa no funciona.
Combinando Spring 3.1 y MyBatis 3
Spring y la inversión de control se encargan precisamente de eliminar código de inicialización y conseguir que el programador se centre en la lógica de negocio que es de lo que se trata.Vamos a inyectar directamente un mapper en un bean de Spring para ver cómo podemos ejecutar la select sin codificar una llamada explícita a SqlSession.
Definimos un bean de spring que tiene una propiedad UserMapper
public class Service implements IService {
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
public void logicaDeNegocio() {
User user = new User();
user.setId("u1");
user.setName("Pocoyo");
user = userMapper.getUser(user);
}
}
Y esto es todo. El servicio Serivce puede invocarse desde la capa de presentación, por ejemplo un action de Struts y la sentencia simplemente se ejecutará. Como véis no hay ni un solo import al API de MyBatis y tampoco lo hay al API de Spring.
Los más suspicaces pensarán que no es posible que esto funcione con tan poco código y efectivamente hemos de confesar que el "codigo" de integración de beans que falta debe estar obligatoriamente en algún lugar y ese lugar es el applicationContext de spring:
Configuración de Spring
<bean id="servicio" class="org.example.Service"> <property name="userMapper" ref="userMapper" /> </bean><bean id="userMapper" class="org.springframework.orm.ibatis3.support.MapperFactoryBean"> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> <property name="mapperInterface" value="org.example.UserMapper" /> </bean>
<bean id="sqlSessionFactory" class="org.springframework.orm.ibatis3.SqlSessionFactoryBean"> <property name="configLocation" value="classpath:org/example/ibatis-config.xml" /> <property name="dataSource" ref="dataSource" /> </bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> <property name="url" value="jdbc:hsqldb:mem:test"/> <property name="username" value="sa"/> <property name="password" value=""/> </bean>
En el ejemplo usamos un datasource de apache commons. Lógicamente a nuestro servicio le podemos dotar de transaccionalidad usando los interceptores de Spring.
Es posible generar automaticamente los DAOs que implementan el CRUD (create, remove..) usando el generador MyBatis (antes denominado iBator).
Eso es todo!
Como véis MyBatis y Spring nos permiten crear programas sin código de persistencia. Externalizando las SQL a un fichero xml externo. Una solución muy adecuada para bases de datos desorganizadas o simplemente para los que les gusta el SQL Ejemplo en: http://jira.springframework.org/secure/attachment/16059/MapperFactoryBean_20100101.tar.gzin j2ee
Reader Comments