Javier Antoniucci

Ingeniero en Informática

Somos expertos en Java/J2EE

Ver todos los tutoriales del autor

Fecha de publicación del tutorial: 2006-09-07

Tutorial visitado 46.935 veces Descargar en PDF

Manual Básico de Apache iBatis


Introducción

¿Qué es iBatis?

Apache iBatis está constituido por dos frameworks independientes que generalmente se usan juntos: DAO y sqlMaps. El primero simplifica la implementación el patrón de diseño Direct Access Objects (DAO) y el segundo simplifica la persistencia de objetos en bases de datos relacionales.

iBatis NO es un ORM (Object Relational Mapper), por lo que se pueden utilizar modelos de datos existentes o poco normalizados y, finalmente, no es completamente transparente (el programador programa el SQL)

Ambos frameworks de iBatis han sido portados a .NET con notable éxito y popularidad. Ambas versiones ya son releases estables y maduras.

¿Para qué sirve?

El patrón DAO nos ayuda a organizar las tareas de persistencia (guardado, búsqueda, recuperación, borrado, etc.) de los objetos y nos permite definir múltiples implementaciones para un mismo objeto mediante la definición de una interfaz. Por ejemplo, la interfaz UsuarioDao tiene los metodos guardarUsuario(Usuario usuario), obtenerUsuario(String loginId), etc y dos implementaciones: UsuarioMySqlDao y UsuarioLdapDao donde implementamos las operaciones para MySql y Ldap respectivamente. Con iBatis DAO podremos configurar cuándo usar una u otra implementación sin necesidad de modificar código. Además, agregar un UsuarioOracleDao será muy fácil y no implicará modificar código del resto de la aplicación.

Cuando hacemos un análisis y diseño orientado a objetos obtenemos nuestro modelo de clases y también diseñamos el modelo de datos donde se almacena la información. Y siempre nos queda la tarea de conectarnos con una base de datos, crear statements, construir selects/updates/etc, recorrer resultsets y setear atributos de objetos, etc. para guardar, buscar, recuperar, etc. los valores de los atributos de un objeto. iBatis sqlMap simplifica esta tarea resumiéndola a la configuración de ficheros XML, con SQL ANSI o propietario y funciona con prácticamente cualquier base de datos con driver JDBC.

¿Cuándo utilizar iBatis?

Como toda herramienta, no vale para todo. iBatis sqlMap es muy válido cuando:


  • Se requiere una curva de aprendizaje rápida y pocos conocimientos previos, y no requiere aprender un lenguaje de consultas como en Hibernate o EJB CMP.

  • Se necesita manipular el SQL (para utilizar SQL propietario, optimizarlo, etc.) o se necesita llamar a procedimientos almacenados.

  • El modelo de datos existe previamente y no está muy normalizado (aunque lógicamente se puede utilizar con modelos nuevos y normalizados)

  • Alto rendimiento y optimización


…pero no para cuando:


  • Se requiere una automatización total y transparente de la persistencia

  • Se requiere soporte multi-RDBMS (motor de base de datos) transparente y automática


Hay una comparación constructiva con Hibernate en http://raibledesigns.com/page/rd?entry=hibernate_vs_ibatis


iBatis DAO es válido cuando:


  • Se sabe que el RDBMS (motor de base de datos) puede cambiar en el futuro

  • La implementación del acceso a datos puede requerir cambios sustanciales en el futuro

  • La implementación del acceso a datos puede variar entre un entorno de producción y otro (software comercial en distintos clientes)


iBatis DAO soporta sqlMap, Hibernate, etc.

¿Cómo funciona esto internamente?

Básicamente, programación declarativa y extensión del framework. Es decir, se configuran ficheros XML y, en iBatis DAO, se extienden clases donde se implementa la interfaz y el comportamiento específico.


Ejemplo:


  1. iBatis DAO (opcional)


    1. Crear un DAO.XML


<!DOCTYPE daoConfig PUBLIC "-//iBATIS.com//DTD DAO Configuration 2.0//EN" "http://www.ibatis.com/dtd/dao-2.dtd">

<daoConfig>

<context>

<transactionManager type="SQLMAP">

<property name="SqlMapConfigResource"

value="es/dxd/km/dao/sqlMap/sqlMapConfig.xml" />

</transactionManager>


<dao interface="es.dxd.km.dao.UsuarioDao"

implementation="es.dxd.km.dao.sqlMap.UsuarioSqlMapDao" />


</context>

</daoConfig>


    1. Crear una utilidad de configuración tipo DaoConfig


public class DaoConfig {


private static final String DAO_XML = "es/dxd/km/dao/dao.xml";


private static final DaoManager daoManager;


static {

try {

daoManager = newDaoManager();

} catch (Exception e) {

throw new RuntimeException("Description. Cause: " + e, e);

}


}


public static DaoManager getDaoManager() {

return daoManager;

}


public static DaoManager newDaoManager() {

try {

Reader reader = Resources.getResourceAsReader(DAO_XML);

return DaoManagerBuilder.buildDaoManager(reader, null);

} catch (Exception e) {

throw new RuntimeException(

"Could not initialize DaoConfig. Cause: " + e, e);

}

}

}


    1. Crear la interfaz del Dao para Usuarios, UsuariosDao:


public interface UsuarioDao extends Dao {

public int updateUsuario(Usuario usuario);

public int insertUsuario(Usuario usuario);

public int deleteUsuario(String idUsuario);

public Usuario getUsuario(String idUsuario);

public Usuario getUsuarioValidado(String idUsuario, String password);

public List getUsuariosByExample(Usuario usuario);

}


    1. Crear su implementación:


public class UsuarioSqlMapDao extends SqlMapDaoTemplate implements

es.dxd.km.dao.UsuarioDao {


public UsuarioSqlMapDao(DaoManager arg0) {

super(arg0);

}


public int updateUsuario(Usuario usuario) {

try {

return getSqlMapExecutor().update("updateUsuario", usuario);

} catch (SQLException e) {

throw new DaoException("Error actualizando usuario. Cause: " + e, e);

}

}


public int insertUsuario(Usuario usuario) {

try {

getSqlMapExecutor().insert("insertUsuario", usuario);

} catch (SQLException e) {

throw new DaoException("Error insertando usuario. Cause: " + e, e);

}

return 1;

}


public int deleteUsuario(String idUsuario) {

try {

return getSqlMapExecutor().delete("deleteUsuario", idUsuario);

} catch (SQLException e) {

throw new DaoException("Error actualizando usuario. Cause: " + e, e);

}

}


public Usuario getUsuario(String idUsuario) {

try {

Usuario usuario = (Usuario) getSqlMapExecutor().queryForObject(

"getUsuarioById", idUsuario);

usuario.setRoles((List) getSqlMapExecutor().queryForList(

"getRolesUsuario", usuario));

return usuario;

} catch (SQLException e) {

throw new DaoException("Error recuperando usuario. Cause: " + e, e);

}

}


public List getUsuariosByExample(Usuario usuario) {

try {

Usuario usuarioExample = new Usuario();

if (usuario.getApellidos() != null) {

usuarioExample.setApellidos("%"

+ usuario.getApellidos().toLowerCase() + "%");

}

if (usuario.getNombre() != null) {

usuarioExample.setNombre("%"

+ usuario.getNombre().toLowerCase() + "%");

}

usuarioExample.setIdUsuario(usuario.getIdUsuario());

List usuarios = (List) getSqlMapExecutor().queryForList(

"getUsuariosByExample", usuarioExample);

// Asignar los roles

for (Iterator iter = usuarios.iterator(); iter.hasNext();) {

Usuario usuario2 = (Usuario) iter.next();

usuario2.setRoles((List) getSqlMapExecutor().queryForList(

"getRolesUsuario", usuario2));

}

return usuarios;

} catch (SQLException e) {

throw new DaoException("Error recuperando usuarios. Cause: " + e, e);

}

}


public Usuario getUsuarioValidado(String idUsuario, String password) {

Usuario usuario = getUsuario(idUsuario);

return usuario.getPassword().equals(password) ? usuario : null;

}


}


  1. iBatis sqlMap


    1. Crear la configuración sqlMapConfig.xml


<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMapConfig

PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"

"http://www.ibatis.com/dtd/sql-map-config-2.dtd">


<sqlMapConfig>


<properties

resource="properties/SqlMapConfig.properties" />


<settings cacheModelsEnabled="true" enhancementEnabled="true"

lazyLoadingEnabled="true" maxRequests="32" maxSessions="10"

maxTransactions="5" useStatementNamespaces="false" />


<transactionManager type="JDBC">

<dataSource type="SIMPLE">

<property name="JDBC.Driver" value="${driver}" />

<property name="JDBC.ConnectionURL" value="${url}" />

<property name="JDBC.Username" value="${username}" />

<property name="JDBC.Password" value="${password}" />

</dataSource>

</transactionManager>


<sqlMap

resource="es/dxd/km/dao/sqlMap/Usuario.xml" />


</sqlMapConfig>


    1. La configuración de contexto es preferible sacarla afuera del xml para, por ejemplo, cambiar fácilmente de entornos, en el sqlMapConfig.xml se indicó que estuviera en properties/SqlMapConfig.properties:


driver=org.apache.derby.jdbc.ClientDriver

url=jdbc:derby://localhost:1527/kmdb

username=derby

password=derby


    1. Finalmente, se configuran las operaciones y su SQL en Usuario.xml:


<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">

<sqlMap namespace="Usuario">


<select id="getUsuarioById" resultClass="es.dxd.km.model.Usuario">

SELECT rtrim(ID_USUARIO) as idUsuario, rtrim(PASSWORD) as

password, rtrim(NOMBRE) as nombre, rtrim(APELLIDOS) as apellidos

FROM APP.USUARIOS WHERE id_usuario = #value#

</select>


<select id="getRolesUsuario"

parameterClass="es.dxd.km.model.Usuario"

resultClass="es.dxd.km.model.Rol">

SELECT rtrim(R.ID_ROL) as idRol, rtrim(R.NOMBRE) as nombre,

rtrim(R.DESCRIPCION) as descripcion FROM APP.ROLES R,

APP.USUARIOS_ROLES U WHERE R.ID_ROL = U.ID_ROL AND U.ID_USUARIO

= #idUsuario#

</select>


<select id="getUsuariosByExample"

parameterClass="es.dxd.km.model.Usuario"

resultClass="es.dxd.km.model.Usuario">

SELECT rtrim(ID_USUARIO) as idUsuario, rtrim(PASSWORD) as

password, rtrim(NOMBRE) as nombre, rtrim(APELLIDOS) as apellidos

FROM APP.USUARIOS

<dynamic prepend="WHERE">

<isNotNull prepend="AND" property="nombre">

lower(NOMBRE) like #nombre#

</isNotNull>

<isNotNull prepend="AND" property="apellidos">

lower(APELLIDOS) like #apellidos#

</isNotNull>

<isNotNull prepend="AND" property="idUsuario">

ID_USUARIO = #idUsuario#

</isNotNull>

</dynamic>

</select>


<insert id="insertUsuario"

parameterClass="es.dxd.km.model.Usuario">

INSERT INTO APP.USUARIOS (ID_USUARIO, PASSWORD, NOMBRE,

APELLIDOS) VALUES (#idUsuario#, #password#, #nombre#,

#apellidos#)

</insert>


<update id="updateUsuario"

parameterClass="es.dxd.km.model.Usuario">

UPDATE APP.USUARIOS SET PASSWORD = #password#, NOMBRE =

#nombre#,APELLIDOS = #apellidos# WHERE ID_USUARIO = #idUsuario#

</update>


<delete id="deleteUsuario" parameterClass="string">

DELETE FROM APP.USUARIOS WHERE ID_USUARIO = #value#

</delete>


</sqlMap>


¿Licencia?

iBatis es un proyecto que pertenece y utilza la licencia de Apache Software Foundation, por lo que es Open Source disponible, modificable y comercializable libremente.
(todo asesoramiento en este tema será bienvenido)

¿Y para qué este manual básico?

Para simplificar el "first touch" y para explicar iBatis a alto nivel.


No pretende ser un tutorial, una guía del usuario ni un manual de referencia. Ellos ya se han escrito y están disponibles en las direcciones que se mencionan en la sección "¿Dónde encuentro más info?"

¿Dónde encuentro más info?

En la Página Oficial http://ibatis.apache.org encontrarán en la sección Documentación unos tutoriales muy buenos aunque extensos, una guía de referencia y el JavaDoc de la API. También tienen una sección de preguntas frecuentes muy completa.


Desde esta página también se puede descargar (recomiendo) el ejemplo oficial de utilización de iBatis: el JPetStore. Viene a ser como el PetStore de J2EE reconvertido a Struts+iBatis.

¿Cómo pongo en funcionamiento iBatis?

Básicamente hay que incluir las librerías en el path (en las aplicaciones web, en /WEB-INF/lib)


Lo ideal es deplegar el war del JPetStore, descargable desde http://ibatis.apache.org, y ver cómo funciona. Hacerle alguna modificación. Comenzar un prototipo desde cero y seguir los tutoriales.


Consejo: ser muy meticuloso con los XML porque la info de debugging es escasa y confusa.

A continuación puedes evaluarlo:

Regístrate para evaluarlo

Por favor, vota +1 o compártelo si te pareció interesante

Share |
Anímate y coméntanos lo que pienses sobre este TUTORIAL:

Fecha publicación: 2014-03-06-00:40:53

Autor: shirley2014

Este tutorial me va a servir para conocer IBATIS, pues aca en Chile lo piden mucho en los perfiles analista programador Java.

Gracias Javier !!!

Fecha publicación: 2012-02-13-18:29:23

Autor: Renzo


Hola, para el caso de Ibatis como puedo obtener un rango de registros, por ejemplo de 100 registros quiero obtenter del 41 al registro 60. algo como <=41 and >=60

Gracias.

Fecha publicación: 2012-02-13-18:29:11

Autor: Renzo


Hola, para el caso de Ibatis como puedo obtener un rango de registros, por ejemplo de 100 registros quiero obtenter del 41 al registro 60. algo como <=41 and >=60

Gracias.

Fecha publicación: 2010-09-14-12:07:41

Autor: jcarmonaloeches

Es una introducción muy buena al framework.

Fecha publicación: 2009-04-27-09:58:33

Autor:

[oscardb] ESTE TUTORIAL ES EL MEJOR QUE HE VISTO EN LA WEB MUCHAS FELICITACIONES!!! Y MUCHAS GRACIAS!!

Fecha publicación: 2007-03-15-11:24:08

Autor:

[Miguel de Francisco ] Sinceramente, muy buena la primera toma de contacto. Te felicito

Fecha publicación: 2006-09-20-05:59:21

Autor:

[alvaro] Me gusto mucho, pero no encontré el JPetStore.

Fecha publicación: 2006-09-13-05:03:24

Autor:

[Adolfo Bravo] Hola me gusto mucho la manera tan sucinta con la explicaron iBatis, gracias

Fecha publicación: 2006-09-09-08:41:17

Autor:

[Carletes] Muy buen tutorial, si señor. ;-) Gracías por tu esfuerzo, dedicación y generosidad al compartir conocimiento.