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

       Copyright ${license.git.copyrightYears} the original author or authors.

       Licensed under the Apache License, Version 2.0 (the "License");
       you may not use this file except in compliance with the License.
       You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing, software
       distributed under the License is distributed on an "AS IS" BASIS,
       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       See the License for the specific language governing permissions and
       limitations under the License.

-->
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">

	<properties>
		<title>MyBatis 3 | Primeros pasos</title>
		<author email="clinton.begin@gmail.com">Clinton Begin</author>
		<author email="eduardo.macarron@gmail.com">Eduardo Macarron</author>
	</properties>

	<body>
		<section name="Primeros pasos">


    <subsection name="Instalación">
      <p>
        Para usar MyBatis sólo tienes que incluir el fichero
        <a href="https://github.com/mybatis/mybatis-3/releases">mybatis-x.x.x.jar</a>
        en el classpath.
      </p>
      <p>
        Si usas Maven añade esta dependencia en tu pom.xml:
      </p>
        <source><![CDATA[
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>]]></source>
    </subsection>

			<subsection name="Cómo crear un SqlSessionFactory a partir de XML">

			<p>
				Una aplicación que usa MyBatis debe utilizar una instancia de
				SqlSessionFactory. Se puede obtener una instancia de
				SqlSessionFactory mediante un SqlSessionFactoryBuilder. Un
				SqlSessionFactoryBuilder
				puede construir una instancia de SqlSessionFactory a partir de un fichero
				de configuración XML o de una
				instancia personalizada de la clase Configuration.
			</p>
				<p>
					Crear una instancia SqlSessionFactory desde un fichero xml es muy
					sencillo. Se recomienda usar un
					classpath resource, pero es posible usar cualquier InputStream, incluso
					creado con un path de fichero o una
					URL de tipo file://. MyBatis proporciona una clase de utilidad,
					llamada Resources, que contiene métodos
					que simplifican la carga de recursos desde el classpath u otras
					ubicaciones.
				</p>
				<source><![CDATA[
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);]]></source>
				<p>
					El fichero de configuración XML contiene la configuración del
					<i>core</i>
					de MyBatis, incluyendo el DataSource
					para obtener instancias de conexión a la base de datos y también un
					TransactionManager para
					determinar cómo deben controlarse las transacciones. Los detalles completos
					de la configuración XML
					se describen más adelante en este documento, pero continuación se
					muestra un ejemplo sencillo:
				</p>
				<source><![CDATA[<?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>
  <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="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>]]></source>
				<p>
					Aunque hay mucha más información sobre el fichero de configuración XML,
					el ejemplo anterior contiene
					las partes más importantes. Observa que hay una cabecera XML,
					requerida para validar el fichero XML.
					El cuerpo del elemento environment contiene la configuración de la
					gestión de transacciones
					correspondiente al entorno. El elemento mappers contiene la lista de mappers – Los
					ficheros XML que
					contienen las sentencias SQL y las definiciones de mapeo.
				</p>
			</subsection>
			<subsection name="Cómo crear un SqlSessionFactory sin XML">
				<p>
					Si lo prefieres puedes crear la configuración directamente desde
					Java, en lugar de desde XML, o crear tu
					propio
					<i>builder</i>
					. MyBatis dispone una clase Configuration que proporciona las
					mismas opciones de
					configuración que el fichero XML.
				</p>
				<source><![CDATA[DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);]]></source>
				<p>
					Puedes observar que en este caso la configuración está añadiendo una
					clase mapper. Las clases mapper
					son clases Java que contienen anotaciones de mapeo SQL que permiten
					evitar el uso de XML. Sin
					embargo el XML sigue siendo necesario en ocasiones, debido a ciertas
					limitaciones de las anotaciones
					Java y la complejidad que pueden alcanzar los mapeos (ej. mapeos
					anidados de Joins). Por esto, MyBatis
					siempre busca si existe un fichero XML asociado a la clase mapper (en este
					caso, se buscará un fichero
					con nombre BlogMapper.xml cuyo nombre deriva del classpath y nombre de
					BlogMapper.class).
					Hablaremos más sobre esto más adelante.
				</p>
			</subsection>
			<subsection
				name="Cómo obtener un SqlSession a partir del SqlSessionFactory">
				<p>
					Ahora que dispones de un SqlSessionFactory, tal y como su nombre indica,
					puedes adquirir una instancia
					de SqlSession. SqlSession contiene todos los métodos necesarios para
					ejecutar sentencias SQL contra la
					base de datos. Puedes ejecutar mapped statements con la instancia de
					SqlSession de la siguiente forma:
				</p>
				<source><![CDATA[try (SqlSession session = sqlSessionFactory.openSession()) {
  Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
}]]></source>
				<p>
					Aunque esta forma de trabajar con la SqlSession funciona correctamente y
					les será familiar a aquellos que han usado las versiones anteriores
					de MyBatis, actualmente existe una opción más recomendada. Usar un
					interface (ej. BlogMapper.class) que describe tanto el parámetro de
					entrada como el de retorno para una sentencia. De esta forma
					tendrás un código más sencillo y type safe, sin castings ni
					literales de tipo String que son fuente frecuente de errores.
				</p>
				<p>
					Por ejemplo:
				</p>
				<source><![CDATA[try (SqlSession session = sqlSessionFactory.openSession()) {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  Blog blog = mapper.selectBlog(101);
}]]></source>
				<p>
					Vemos con detalle cómo funciona esto.
				</p>
			</subsection>
			<subsection name="Cómo funcionan los Mapped Statements">
				<p>
					Te estarás preguntando qué se está ejecutando en SqlSession o en la
					clase Mapper. Los
					<i>Mapped Statements</i>
					son una materia muy densa, y será el tema que domine la mayor parte
					de esta documentación. Pero, para que te hagas una idea de qué se
					está ejecutando realmente proporcionaremos un par de ejemplos.
				</p>
				<p>
					En cualquiera de los ejemplos a continuación podrían haberse usado
					indistintamente XML o anotaciones. Veamos primero el XML. Todas las
					opciones de configuración de MyBatis pueden obtenerse mediante el
					lenguaje de mapeo XML que ha popularizado a MyBatis durante años.
					Si ya has usado MyBatis antes el concepto te será familiar, pero
					verás que hay numerosas mejoras en los ficheros de mapeo XML que
					iremos explicando más adelante. Por ejemplo este mapped statement
					en XML haría funcionar correctamente la llamada al SqlSession que
					hemos visto previamente.
				</p>
				<source><![CDATA[<?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="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>]]></source>
				<p>
					Aunque pudiera parecer que hay excesivo XML para un ejemplo tan simple,
					en realidad no hay tanto. Puedes definir tantos mapped statements
					en un solo fichero XML como quieras así que rentabilizarás las
					líneas XML extra que corresponden a la cabecera XML y a la
					declaración de doctype. El resto del fichero se explica por sí
					mismo. Define un nombre para el mapped statement “selectBlog”, en
					un namespace (espacio de nombres) “org.mybatis.example.BlogMapper”,
					que permite realizar una llamada especificando el nombre completo
					(fully qualified) “org.mybatis.example.BlogMapper.selectBlog” tal y
					como muestra el código a continuación:
				</p>
				<source><![CDATA[Blog blog = session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);]]></source>
				<p>
					Observa el gran parecido que hay entre esta llamada y la llamada a una
					clase java y hay una razón para eso. Este literal puede mapearse
					con una clase que tenga el mismo nombre que el namespace, con un
					método que coincida con el nombre del statement, y con parámetros
					de entrada y retorno iguales que los del statement. Esto permite
					que puedas hacer la misma llamada contra una interfaz Mapper tal y
					como se muestra a continuación:
				</p>
				<source><![CDATA[BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);]]></source>
				<p>
					Este segunda forma de llamada tiene muchas ventajas. Primeramente, no
					se usan literales de tipo String lo cual es mucho más seguro dado
					que los errores se detectan en tiempo de compilación. Segundo, si
					tu IDE dispone de autocompletado de código podrás aprovecharlo.
				</p>
				<hr />
				<p>
					<span class="label important">NOTA</span>
					<strong>Una nota sobre los namespaces.</strong>
				</p>
				<p>
					<strong>Los namespaces (espacios de nombres)</strong>
					eran opcionales en versiones anteriores de MyBatis, lo cual creaba
					confusión y era de poca ayuda. Los namespaces son ahora
					obligatorios y tienen un propósito más allá de la clasificación de
					statements.
				</p>
				<p>
					Los namespaces permiten realizar el enlace con los interfaces como se
					ha visto anteriormente, e incluso si crees que no los vas a usar a
					corto plazo, es recomendable que sigas estas prácticas de
					organización de código por si en un futuro decides hacer lo
					contrario. Usar un namespace y colocarlo en el paquete java que
					corresponde con el namespace hará tu código más legible y mejorará
					la usabilidad de MyBatis a largo plazo.
				</p>
				<p>
					<strong>Resolución de nombres:</strong>
					Para reducir la cantidad de texto a escribir MyBatis usa las
					siguientes normas de resolución de nombres para todos los elementos
					de configuración, incluidos statements, result maps, cachés, etc.
				</p>
				<ul>
					<li>Primeramente se buscan directamente los nombres completamente
						cualificados (fully qualified names) (ej.
						“com.mypackage.MyMapper.selectAllThings”).
					</li>
					<li>Pueden usarse los nombres cortos (ej. “selectAllThings”)
						siempre que no haya ambigüedad. Sin embargo, si hubiera dos o más
						elementos (ej. “com.foo.selectAllThings" y
						"com.bar.selectAllThings”), entonces obtendrás un error indicando
						que el nombre es ambiguo y que debe ser “fully qualified”.
					</li>
				</ul>
				<hr />
				<p>
					Hay otro aspecto importante sobre las clases Mapper como BlogMapper.
					Sus mapped statements pueden no estar en ningún fichero XML. En su
					lugar, pueden usarse anotaciones. Por ejemplo, el XML puede ser
					eliminado y reemplazarse por:
				</p>
				<source><![CDATA[package org.mybatis.example;
public interface BlogMapper {
  @Select("SELECT * FROM blog WHERE id = #{id}")
  Blog selectBlog(int id);
}]]></source>
				<p>
					Las anotaciones son mucho más claras para sentencias sencillas, sin
					embargo, las anotaciones java son limitadas y más complicadas de
					usar para sentencias complejas. Por lo tanto, si tienes que hacer
					algo complejo, es mejor que uses los ficheros XML.
				</p>
				<p>
					Es decisión tuya y de tu proyecto cuál de los dos métodos usar y cómo
					de importante es que los mapped statements estén definidos de forma
					consistente. Dicho esto, no estás limitado a usar un solo método,
					puedes migrar fácilmente de los mapped statements basados en
					anotaciones a XML y viceversa.
				</p>
			</subsection>
			<subsection name="Ámbito y ciclo de vida">
				<p>Es muy importante entender los distintos ámbitos y ciclos de vida
					de las clases de las que hemos hablado hasta ahora. Usarlas de
					forma incorrecta puede traer serias complicaciones.</p>
				<hr />
				<p>
					<span class="label important">NOTA</span>
					<strong>Ciclo de vida de los objetos y frameworks de inyección de
						dependencias</strong>
				</p>
				<p>
					Los frameworks de inyección de dependencias pueden crear
					SqlSessions y mappers
					<i>thread safe</i>
					(reeentrante) y
					transaccionales, e inyectarlos directmaente en tus beans de forma que puedes
					olvidarte de su ciclo de vida.
					Echa un vistazo a los sub-projectos MyBatis-Spring o MyBatis-Guice para
					conocer más detalles sobre cómo usar
					MyBatis con estos frameworks.
				</p>
				<hr />

				<h4>SqlSessionFactoryBuilder</h4>
				<p>Esta clase puede instanciarse, usarse y desecharse. No es
					necesario mantenerla una vez que ya has creado la
					SqlSessionFactory. Por lo tanto el mejor ámbito para el
					SqlSessionFactoryBuilder es el método (ej. una variable local de
					método). Puedes reusar el SqlSessionFactoryBuilder para construir
					más de una instancia de SqlSessionFactory, pero aun así es
					recomendable no conservar el objeto para asegurarse de que todos
					los recursos utilizados para el parseo de XML se han liberado
					correctamente y están disponibles para temas más importantes.
				</p>
				<h4>SqlSessionFactory</h4>
				<p>Una vez creado, el SqlSessionFactory debería existir durante toda
					la ejecución de tu aplicación. No debería haber ningún o casi
					ningún motivo para eliminarlo o recrearlo. Es una buena práctica el
					no recrear el SqlSessionFactory en tu aplicación más de una vez. Y
					lo contrario debería considerarse código sospechoso. Por tanto el
					mejor ámbito para el SqlSessionFactory es el ámbito de aplicación.
					Esto puede conseguirse de muchas formas. Lo más sencillo es usar el
					patrón Singleton o el Static Singleton. </p>
				<h4>SqlSession</h4>
				<p>Cada thread (hilo de ejecución) debería tener su propia instancia
					de SqlSession. Las instancias de SqlSession no son thread safe y no
					deben ser compartidas. Por tanto el ámbito adecuado es el de
					petición (request) o bien el método. No guardes nunca instancias de
					SqlSession en un campo estático o incluso en una propiedad de
					instancia de una clase. Nunca guardes referencias a una SqlSession
					en ningún tipo de ámbito gestionado como la HttpSession. Si estás
					usando un framework web considera que el SqlSession debería tener
					un ámbito similar al HttpRequest. Es decir, cuando recibas una
					petición http puedes abrir una SqlSession y cerrarla cuando
					devuelvas la respuesta. Cerrar la SqlSession es muy importante.
					Deberías asegurarte de que se cierra con un bloque finally. A
					continuación se muestra el patrón estándar para asegurarse de que
					las sesiones se cierran correctamente.</p>
				<source><![CDATA[try (SqlSession session = sqlSessionFactory.openSession()) {
  // do work
}]]></source>
				<p>Usando este patrón en todo el código se asegura que los recursos
					de base de datos se liberarán correctamente.</p>
				<h4>Instancias de mapper</h4>
				<p>Los mappers son interfaces que creas como enlace con los mapped
					statements. Las instancias de mappers se obtienen de una
					SqlSession. Y por tanto, técnicamente el mayor ámbito de una
					instancia de Mapper es el mismo que el de la SqlSession de la que
					fueron creados. Sin embargo el ámbito más recomendable para una
					instancia de mapper es el ámbito de método. Es decir, deberían ser
					obtenidos en el método que vaya a usarlos y posteriormente
					descartarlos. No es necesario que sean cerrados explícitamente.
					Aunque no es un problema propagar estos objetos por varias clases
					dentro de una misma llamada, debes tener cuidado porque puede que
					la situación se te vaya de las manos. Hazlo fácil (keep it simple)
					y mantén los mappers en el ámbito de método. Este ejemplo muestra
					esta práctica:</p>
				<source><![CDATA[try (SqlSession session = sqlSessionFactory.openSession()) {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  // do work
}
]]></source>

			</subsection>
		</section>
	</body>
</document>
