<?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 | Configuración</title>
    <author email="clinton.begin@gmail.com">Clinton Begin</author>
    <author email="eduardo.macarron@gmail.com">Eduardo Macarron</author>
  </properties>

  <body>
    <section name="Configuración">
      <p>El fichero de configuración XML contiene parámetros y configuraciones que tienen un efecto crucial en cómo se comporta MyBatis. A alto nivel contiene:</p>

      <ul>
        <li>
          configuration
          <ul>
            <li><a href="#properties">properties</a></li>
            <li><a href="#settings">settings</a></li>
            <li><a href="#typeAliases">typeAliases</a></li>
            <li><a href="#typeHandlers">typeHandlers</a></li>
            <li><a href="#objectFactory">objectFactory</a></li>
            <li><a href="#plugins">plugins</a></li>
            <li><a href="#environments">environments</a>
              <ul>
                <li>
                  environment
                  <ul>
                    <li>transactionManager</li>
                    <li>dataSource</li>
                  </ul>
                </li>
              </ul>
            </li>
            <li><a href="#databaseIdProvider">databaseIdProvider</a></li>
            <li><a href="#mappers">mappers</a></li>
          </ul>
        </li>
      </ul>
      <subsection name="properties">
        <p>Contiene propiedades externalizables y sustituibles que se pueden configurar en un típico properties de Java o bien puede definirse su contenido directamente mediante subelementos property. Por ejemplo:
        </p>
        <source><![CDATA[<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>]]></source>
        <p>Las propiedades pueden usarse a lo largo del fichero de configuración para sustituir valores que deben configurarse dinámicamente. Por ejemplo:
        </p>
        <source><![CDATA[<dataSource type="POOLED">
  <property name="driver" value="${driver}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
</dataSource>]]></source>
        <p>El usuario y password de este ejemplo se reemplazarán por los valores de los elementos de tipo property. El driver y la url se reemplazarán por los valores contenidos en el fichero config.properties.  Esto aumenta mucho las posibilidades de configuración.
        </p>
        <p>Las propiedades también pueden pasarse como parámetro al método SqlSessionFactoryBuilder.build(). Por ejemplo:
        </p>
        <source><![CDATA[SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props);

// ... or ...

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);
]]></source>
        <p>Si una propiedad existe en más de un lugar, MyBatis la carga en este orden:
        </p>
        <ul>
          <li>Primero se leen las propiedades especificadas en el elemento XML properties,
          </li>
          <li>Posteriormente se cargan las propiedades de recursos de tipo classpath o url del elementos properties, si hubiera una propiedad repetida sería sobrescrita,
          </li>
          <li>Y finalmente se leen las propiedades pasadas como parámetro, que en caso de duplicidad sobrescriben las propiedades que se hayan cargado del elemento properties o de recursos/url.
          </li>
        </ul>
        <p>Por tanto las properties más prioritarias son las pasadas como parámetro, seguidas de los atributos tipo classpath/url y finalmente las propiedades especificadas en el elemento properties..
        </p>

        <p>
          Since the MyBatis 3.4.2, your can specify a default value into placeholder as follow:
        </p>
        <source><![CDATA[
<dataSource type="POOLED">
  <!-- ... -->
  <property name="username" value="${username:ut_user}"/> <!-- If 'username' property not present, username become 'ut_user' -->
</dataSource>]]></source>

        <p>
          This feature is disabled by default. If you specify a default value into placeholder,
          you should be enable this feature by adding a special property as follow:
        </p>

        <source><![CDATA[
<properties resource="org/mybatis/example/config.properties">
  <!-- ... -->
  <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <!-- Enable this feature -->
</properties>]]></source>

        <p>
          <span class="label important">NOTE</span> Also If you are used already the <code>":"</code> as property key(e.g. <code>db:username</code>)
          or you are used already the ternary operator of OGNL expression(e.g. <code>${tableName != null ? tableName : 'global_constants'}</code>) on your sql definition,
          you should be change the character that separate key and default value by adding a special property as follow:
        </p>

        <source><![CDATA[
<properties resource="org/mybatis/example/config.properties">
  <!-- ... -->
  <property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="?:"/> <!-- Change default value of separator -->
</properties>]]></source>
        <source><![CDATA[
<dataSource type="POOLED">
  <!-- ... -->
  <property name="username" value="${db:username?:ut_user}"/>
</dataSource>]]></source>

      </subsection>
      <subsection name="settings">
        <p>Son muy importantes para definir cómo se comporta MyBatis en ejecución. La siguiente tabla describe las configuraciones (settings), sus significados y sus valores por defecto.</p>
        <table>
          <thead>
            <tr>
              <th>Configuración</th>
              <th>Descripción</th>
              <th>Valores admitidos</th>
              <th>Valor por defecto</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>
                cacheEnabled
              </td>
              <td>Habilita o inhabilita globalmente todas las cachés definidas en el mapper
              </td>
              <td>
                true | false
              </td>
              <td>
                true
              </td>
            </tr>
            <tr>
              <td>
                lazyLoadingEnabled
              </td>
              <td>
                Habilita o inhabilita globalmente la carga diferida (lazy loading). Cuando está activo, todas las relaciones se cargan en modo diferido.
                Este valor se puede sobrescribir en cada relación usando el atributo <code>fetchType</code>.
              </td>
              <td>
                true | false
              </td>
              <td>
                false
              </td>
            </tr>
            <tr>
              <td>
                aggressiveLazyLoading
              </td>
              <td>
                When enabled, any method call will load all the lazy properties of the object. Otherwise, each property is loaded on demand (see also <code>lazyLoadTriggerMethods</code>).
              </td>
              <td>
                true | false
              </td>
              <td>
                false (true in ≤3.4.1)
              </td>
            </tr>
            <tr>
              <td>
                multipleResultSetsEnabled
              </td>
              <td>Habilita o inhabilita la obtención de múltiples ResultSets con una sola sentencia (se requiere un driver compatible)
              </td>
              <td>
                true | false
              </td>
              <td>
                true
              </td>
            </tr>
            <tr>
              <td>
                useColumnLabel
              </td>
              <td>Utiliza la etiqueta de columna (label) en lugar del nombre de conlumna. Algunos drivers se comportan distinto en lo que a esto respecta. Consulta la documentación del driver o prueba ambos modos para descubrir cómo funciona tu driver
              </td>
              <td>
                true | false
              </td>
              <td>
                true
              </td>
            </tr>
            <tr>
              <td>
                useGeneratedKeys
              </td>
              <td>Habilita el uso del soporte JDBC para claves autogeneradas. Se requiere un driver compatible. Este parámetro fuerza el uso de las claves autogeneradas si está habilitado. Algunos drivers indican que no son compatibles aunque funcionan correctamente (ej. Derby)
              </td>
              <td>
                true | false
              </td>
              <td>
                False
              </td>
            </tr>
            <tr>
              <td>
                autoMappingBehavior
              </td>
              <td>Especifica cómo deben mapearse de forma automática las columnas a los campos/propiedades. NONE desactiva el mapeo automático. PARTIAL sólo mapea automáticamente los resultados que no contienen result maps anidados en su interior. FULL mapea resultados de cualquier complejidad (contengan anidados o no).
              </td>
              <td>
                NONE, PARTIAL, FULL
              </td>
              <td>
                PARTIAL
              </td>
            </tr>
            <tr>
              <td>
                autoMappingUnknownColumnBehavior
              </td>
              <td>
                Specify the behavior when detects an unknown column (or unknown property type) of automatic mapping target.
                <ul>
                  <li><code>NONE</code>: Do nothing</li>
                  <li><code>WARNING</code>: Output warning log (The log level of <code>'org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'</code> must be set to <code>WARN</code>)</li>
                  <li><code>FAILING</code>: Fail mapping (Throw <code>SqlSessionException</code>)</li>
                </ul>
              </td>
              <td>
                NONE, WARNING, FAILING
              </td>
              <td>
                NONE
              </td>
            </tr>
            <tr>
              <td>
                defaultExecutorType
              </td>
              <td>Configura el ejecutor (executor) por defecto. SIMPLE no hace nada especial. REUSE reúsa prepared statements. BATCH reúsa statements y ejecuta actualizaciones en batch.</td>
              <td>
                SIMPLE
                REUSE
                BATCH
              </td>
              <td>
                SIMPLE
              </td>
            </tr>
            <tr>
              <td>
                defaultStatementTimeout
              </td>
              <td>Establece el número de segundos que debe esperar el driver la respuesta de la base de datos.
              </td>
              <td>
                Cualquier entero positivo
              </td>
              <td>
                Sin valor (null)
              </td>
            </tr>
            <tr>
              <td>
                defaultFetchSize
              </td>
              <td>
                Sets the driver a hint as to control fetching size for return results.
                This parameter value can be override by a query setting.
              </td>
              <td>
                Cualquier entero positivo
              </td>
              <td>
                Sin valor (null)
              </td>
            </tr>
            <tr>
              <td>
                defaultResultSetType
              </td>
              <td>
                Specifies a scroll strategy when omit it per statement settings. (Since: 3.5.2)
              </td>
              <td>
                FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(same behavior with 'Not Set')
              </td>
              <td>
                Not Set (null)
              </td>
            </tr>
            <tr>
              <td>
                safeRowBoundsEnabled
              </td>
              <td>Habilita el uso de RowBounds en statements anidados.
                If allow, set the false.
              </td>
              <td>
                true | false
              </td>
              <td>
                False
              </td>
            </tr>
            <tr>
              <td>
                safeResultHandlerEnabled
              </td>
              <td>
                Habilita el uso de ResultHandler en statements anidados.
                If allow, set the false.
              </td>
              <td>
                true | false
              </td>
              <td>
                True
              </td>
            </tr>
            <tr>
              <td>
                mapUnderscoreToCamelCase
              </td>
              <td>Mapea automáticamente los nombres clásicos de columnas de base de datos A_COLUMN a nombres clásicos de propiedades Java aColumn.
              </td>
              <td>
                true | false
              </td>
              <td>
                False
              </td>
            </tr>
            <tr>
              <td>
                localCacheScope
              </td>
              <td>
              	MyBatis usa una cache local para evitar dependencias circulares y acelerar ejecuciones repeticas de queries anidadas.
              	Por defecto (SESSION) todas las queries ejecutadas en una sesión se cachean. Si localCacheScope=STATEMENT
              	la sesión local solo se usará durante la ejecución de un statement, no se comparten datos entre distintas llamadas
              	a SqlSession.
              </td>
              <td>
                SESSION | STATEMENT
              </td>
              <td>
                SESSION
              </td>
            </tr>
            <tr>
              <td>
                jdbcTypeForNull
              </td>
              <td>
                Permite especificar el tipo JDBC que
                Especifica el tipo JDBC para valores nulos cuando no se ha especificado un tipo concreto para el parámetro.
                Algunos drivers requieren que se indique el tipo JDBC de la columna pero otros permite valores genéricos como NULL, VARCHAR or OTHER.
              </td>
              <td>
                JdbcType enumeration. Los más comunes son: NULL, VARCHAR and OTHER
              </td>
              <td>
                OTHER
              </td>
            </tr>
            <tr>
              <td>
                lazyLoadTriggerMethods
              </td>
              <td>
                Permite especificar qué métodos de Object disparan la carga diferida
              </td>
              <td>
                Lista de métodos separados por comas
              </td>
              <td>
                equals,clone,hashCode,toString
              </td>
            </tr>
            <tr>
              <td>
                defaultScriptingLanguage
              </td>
              <td>
                Permite especificar que lenguaje se usará en el SQL dinámico.
              </td>
              <td>
                Un type alias o una nombre de clase completamente cualificado
              </td>
              <td>
                org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
              </td>
            </tr>
            <tr>
              <td>
                defaultEnumTypeHandler
              </td>
              <td>
                Specifies the <code>TypeHandler</code> used by default for Enum. (Since: 3.4.5)
              </td>
              <td>
                A type alias or fully qualified class name.
              </td>
              <td>
                org.apache.ibatis.type.EnumTypeHandler
              </td>
            </tr>
            <tr>
              <td>
                callSettersOnNulls
              </td>
              <td>
                Permite especificar si se invocarán a los setters y a los métodos put de los mapas si el valor obtenido es null.
                Te en cuenta que si se activa las propiedades que puedan ser informadas con nulos no pueden ser de tipos primitivos.
              </td>
              <td>
                true | false
              </td>
              <td>
                false
              </td>
            </tr>
            <tr>
              <td>
                returnInstanceForEmptyRow
              </td>
              <td>
                MyBatis, by default, returns <code>null</code> when all the columns of a returned row are NULL.
                When this setting is enabled, MyBatis returns an empty instance instead.
                Note that it is also applied to nested results (i.e. collectioin and association). Since: 3.4.2
              </td>
              <td>
                true | false
              </td>
              <td>
                false
              </td>
            </tr>
            <tr>
              <td>
                logPrefix
              </td>
              <td>
                Permite especificar el prefijo que MyBatis añadirá a los nombres de logger.
              </td>
              <td>
                Cualquier cadena
              </td>
              <td>
                No informado
              </td>
            </tr>
            <tr>
              <td>
                logImpl
              </td>
              <td>
                Permite especificar qué implementación de logging utilizar. Si no está informado la impelmentación se descubrirá automaticamente.
              </td>
              <td>
                SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING
              </td>
              <td>
                No informado
              </td>
            </tr>
            <tr>
              <td>
                proxyFactory
              </td>
              <td>
                Permite especificar qué herramienta de generación de proxys se usará para crear los objetos con capacidad de carga lazy.
              </td>
              <td>
                CGLIB | JAVASSIST
              </td>
              <td>
                JAVASSIST (MyBatis 3.3 or above)
              </td>
            </tr>
            <tr>
              <td>
                vfsImpl
              </td>
              <td>
                Specifies VFS implementations
              </td>
              <td>
                Fully qualified class names of custom VFS implementation separated by commas.
              </td>
              <td>
                Not set
              </td>
            </tr>
            <tr>
              <td>
                useActualParamName
              </td>
              <td>
                Allow referencing statement parameters by their actual names declared in the method signature.
                To use this feature, your project must be compiled in Java 8 with <code>-parameters</code> option. (Since: 3.4.1)
              </td>
              <td>
                true | false
              </td>
              <td>
                true
              </td>
            </tr>
            <tr>
              <td>
                configurationFactory
              </td>
              <td>
                Specifies the class that provides an instance of <code>Configuration</code>.
                The returned Configuration instance is used to load lazy properties of deserialized objects.
                This class must have a method with a signature <code>static Configuration getConfiguration()</code>. (Since: 3.2.3)
              </td>
              <td>
                A type alias or fully qualified class name.
              </td>
              <td>
                Not set
              </td>
            </tr>
          </tbody>
        </table>
        <p>
A continuación se muestra un ejemplo del elemento settings al completo:
        </p>
        <source><![CDATA[<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>]]></source>

      </subsection>
      <subsection name="typeAliases">
        <p>Un type alias es simplemente un alias (un nombre más corto) para un tipo Java. Solo es importante para la configuración XML y existe para reducir la cantidad de texto al teclear nombres de clase cualificados (fully qualified). Por ejemplo:
        </p>
        <source><![CDATA[<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
  <typeAlias alias="Comment" type="domain.blog.Comment"/>
  <typeAlias alias="Post" type="domain.blog.Post"/>
  <typeAlias alias="Section" type="domain.blog.Section"/>
  <typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
]]></source>
        <p>
        Con esta configuración, puede usarse <code>Blog</code> en lugar de <code>domain.blog.Blog</code>
        </p>
        <p>
        Tambien puedes indicar un paquete para que MyBatis busque beans de tipo alias. Por ejemplo:
        </p>
        <source><![CDATA[<typeAliases>
  <package name="domain.blog"/>
</typeAliases>
]]></source>
        <p>
        Cada bean encontrado en <code>domain.blog</code>, en caso de que no contenga ninguna anotación,
        se registrará como alias usando su nombre no cualificado en minúsculas. Es decir, <code>domain.blog.Author</code>
        se registrará como will be registered as <code>author</code>.
        Si se encuentra la anotación <code>@Alias</code> se usará su valor como alias. Mira el ejemplo a continuación:
        </p>
        <source><![CDATA[@Alias("author")
public class Author {
    ...
}
]]></source>
        <p>Hay muchos type aliases pre construidos. No son sensibles a mayúsculas/minúsculas. Observa los nombres especiales de los tipos primitivos dadas las colisiones de nombres.
        </p>
        <table>
          <thead>
            <tr>
              <th>
                Alias
              </th>
              <th>
                Tipo mapeado
              </th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>
                _byte
              </td>
              <td>
                byte
              </td>
            </tr>
            <tr>
              <td>
                _long
              </td>
              <td>
                long
              </td>
            </tr>
            <tr>
              <td>
                _short
              </td>
              <td>
                short
              </td>
            </tr>
            <tr>
              <td>
                _int
              </td>
              <td>
                int
              </td>
            </tr>
            <tr>
              <td>
                _integer
              </td>
              <td>
                int
              </td>
            </tr>
            <tr>
              <td>
                _double
              </td>
              <td>
                double
              </td>
            </tr>
            <tr>
              <td>
                _float
              </td>
              <td>
                float
              </td>
            </tr>
            <tr>
              <td>
                _boolean
              </td>
              <td>
                boolean
              </td>
            </tr>
            <tr>
              <td>
                string
              </td>
              <td>
                String
              </td>
            </tr>
            <tr>
              <td>
                byte
              </td>
              <td>
                Byte
              </td>
            </tr>
            <tr>
              <td>
                long
              </td>
              <td>
                Long
              </td>
            </tr>
            <tr>
              <td>
                short
              </td>
              <td>
                Short
              </td>
            </tr>
            <tr>
              <td>
                int
              </td>
              <td>
                Integer
              </td>
            </tr>
            <tr>
              <td>
                integer
              </td>
              <td>
                Integer
              </td>
            </tr>
            <tr>
              <td>
                double
              </td>
              <td>
                Double
              </td>
            </tr>
            <tr>
              <td>
                float
              </td>
              <td>
                Float
              </td>
            </tr>
            <tr>
              <td>
                boolean
              </td>
              <td>
                Boolean
              </td>
            </tr>
            <tr>
              <td>
                date
              </td>
              <td>
                Date
              </td>
            </tr>
            <tr>
              <td>
                decimal
              </td>
              <td>
                BigDecimal
              </td>
            </tr>
            <tr>
              <td>
                bigdecimal
              </td>
              <td>
                BigDecimal
              </td>
            </tr>
            <tr>
              <td>
                object
              </td>
              <td>
                Object
              </td>
            </tr>
            <tr>
              <td>
                map
              </td>
              <td>
                Map
              </td>
            </tr>
            <tr>
              <td>
                hashmap
              </td>
              <td>
                HashMap
              </td>
            </tr>
            <tr>
              <td>
                list
              </td>
              <td>
                List
              </td>
            </tr>
            <tr>
              <td>
                arraylist
              </td>
              <td>
                ArrayList
              </td>
            </tr>
            <tr>
              <td>
                collection
              </td>
              <td>
                Collection
              </td>
            </tr>
            <tr>
              <td>
                iterator
              </td>
              <td>
                Iterator
              </td>
            </tr>
          </tbody>
        </table>
      </subsection>
      <subsection name="typeHandlers">
        <p>Cuando MyBatis establece el valor de un parámetro de un PreparedStatement u obtiene un valor de un ResultSet, se utiliza un TypeHandler para convertir el valor al tipo Java apropiado. La siguiente tabla recoge los TypeHandlers predefinidos.
        </p>
        <p>
          <span class="label important">NOTE</span>
          Since version 3.4.5, The MyBatis has been supported JSR-310(Date and Time API) by default.
        </p>
        <table>
          <thead>
            <tr>
              <th>
                Type Handler
              </th>
              <th>
                Tipos Java
              </th>
              <th>
                Tipos JDBC
              </th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>
                <code>BooleanTypeHandler</code>
              </td>
              <td>
                <code>java.lang.Boolean</code>, <code>boolean</code>
              </td>
              <td>
                Cualquiera compatible con <code>BOOLEAN</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>ByteTypeHandler</code>
              </td>
              <td>
                <code>java.lang.Byte</code>, <code>byte</code>
              </td>
              <td>
                Cualquiera compatible con <code>NUMERIC</code> o <code>BYTE</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>ShortTypeHandler</code>
              </td>
              <td>
                <code>java.lang.Short</code>, <code>short</code>
              </td>
              <td>
                Cualquiera compatible con <code>NUMERIC</code> o <code>SMALLINT</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>IntegerTypeHandler</code>
              </td>
              <td>
                <code>java.lang.Integer</code>, <code>int</code>
              </td>
              <td>
                Cualquiera compatible con <code>NUMERIC</code> o <code>INTEGER</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>LongTypeHandler</code>
              </td>
              <td>
                <code>java.lang.Long</code>, <code>long</code>
              </td>
              <td>
                Cualquiera compatible con <code>NUMERIC</code> o <code>BIGINT</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>FloatTypeHandler</code>
              </td>
              <td>
                <code>java.lang.Float</code>, <code>float</code>
              </td>
              <td>
                Cualquiera compatible con <code>NUMERIC</code> o <code>FLOAT</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>DoubleTypeHandler</code>
              </td>
              <td>
                <code>java.lang.Double</code>, <code>double</code>
              </td>
              <td>
                Cualquiera compatible con <code>NUMERIC</code> o <code>DOUBLE</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>BigDecimalTypeHandler</code>
              </td>
              <td>
                <code>java.math.BigDecimal</code>
              </td>
              <td>
                Cualquiera compatible con <code>NUMERIC</code> o <code>DECIMAL</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>StringTypeHandler</code>
              </td>
              <td>
                <code>java.lang.String</code>
              </td>
              <td>
                <code>CHAR</code>, <code>VARCHAR</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>ClobReaderTypeHandler</code>
              </td>
              <td>
                <code>java.io.Reader</code>
              </td>
              <td>
                -
              </td>
            </tr>
            <tr>
              <td>
                <code>ClobTypeHandler</code>
              </td>
              <td>
                <code>java.lang.String</code>
              </td>
              <td>
                <code>CLOB</code>, <code>LONGVARCHAR</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>NStringTypeHandler</code>
              </td>
              <td>
                <code>java.lang.String</code>
              </td>
              <td>
                <code>NVARCHAR</code>, <code>NCHAR</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>NClobTypeHandler</code>
              </td>
              <td>
                <code>java.lang.String</code>
              </td>
              <td>
                <code>NCLOB</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>BlobInputStreamTypeHandler</code>
              </td>
              <td>
                <code>java.io.InputStream</code>
              </td>
              <td>
                -
              </td>
            </tr>
            <tr>
              <td>
                <code>ByteArrayTypeHandler</code>
              </td>
              <td>
                <code>byte[]</code>
              </td>
              <td>
                Cualquiera compatible con byte stream
              </td>
            </tr>
            <tr>
              <td>
                <code>BlobTypeHandler</code>
              </td>
              <td>
                <code>byte[]</code>
              </td>
              <td>
                <code>BLOB</code>, <code>LONGVARBINARY</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>DateTypeHandler</code>
              </td>
              <td>
                <code>java.util.Date</code>
              </td>
              <td>
                <code>TIMESTAMP</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>DateOnlyTypeHandler</code>
              </td>
              <td>
                <code>java.util.Date</code>
              </td>
              <td>
                <code>DATE</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>TimeOnlyTypeHandler</code>
              </td>
              <td>
                <code>java.util.Date</code>
              </td>
              <td>
                <code>TIME</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>SqlTimestampTypeHandler</code>
              </td>
              <td>
                <code>java.sql.Timestamp</code>
              </td>
              <td>
                <code>TIMESTAMP</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>SqlDateTypeHandler</code>
              </td>
              <td>
                <code>java.sql.Date</code>
              </td>
              <td>
                <code>DATE</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>SqlTimeTypeHandler</code>
              </td>
              <td>
                <code>java.sql.Time</code>
              </td>
              <td>
                <code>TIME</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>ObjectTypeHandler</code>
              </td>
              <td>
                Any
              </td>
              <td>
                <code>OTHER</code>, or unspecified
              </td>
            </tr>
            <tr>
              <td>
                <code>EnumTypeHandler</code>
              </td>
              <td>
                Enumeration Type
              </td>
              <td>
                <code>VARCHAR</code> Cualquiera compatible con string porque se guarda el código (no el índice).
              </td>
            </tr>
            <tr>
              <td>
                <code>EnumOrdinalTypeHandler</code>
              </td>
              <td>
                Enumeration Type
              </td>
              <td>
                Cualquiera compatible con <code>NUMERIC</code> o <code>DOUBLE</code> por que se guarda la posición (no el código).
              </td>
            </tr>
            <tr>
              <td>
                <code>SqlxmlTypeHandler</code>
              </td>
              <td>
                <code>java.lang.String</code>
              </td>
              <td>
                <code>SQLXML</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>InstantTypeHandler</code>
              </td>
              <td>
                <code>java.time.Instant</code>
              </td>
              <td>
                <code>TIMESTAMP</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>LocalDateTimeTypeHandler</code>
              </td>
              <td>
                <code>java.time.LocalDateTime</code>
              </td>
              <td>
                <code>TIMESTAMP</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>LocalDateTypeHandler</code>
              </td>
              <td>
                <code>java.time.LocalDate</code>
              </td>
              <td>
                <code>DATE</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>LocalTimeTypeHandler</code>
              </td>
              <td>
                <code>java.time.LocalTime</code>
              </td>
              <td>
                <code>TIME</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>OffsetDateTimeTypeHandler</code>
              </td>
              <td>
                <code>java.time.OffsetDateTime</code>
              </td>
              <td>
                <code>TIMESTAMP</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>OffsetTimeTypeHandler</code>
              </td>
              <td>
                <code>java.time.OffsetTime</code>
              </td>
              <td>
                <code>TIME</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>ZonedDateTimeTypeHandler</code>
              </td>
              <td>
                <code>java.time.ZonedDateTime</code>
              </td>
              <td>
                <code>TIMESTAMP</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>YearTypeHandler</code>
              </td>
              <td>
                <code>java.time.Year</code>
              </td>
              <td>
                <code>INTEGER</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>MonthTypeHandler</code>
              </td>
              <td>
                <code>java.time.Month</code>
              </td>
              <td>
                <code>INTEGER</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>YearMonthTypeHandler</code>
              </td>
              <td>
                <code>java.time.YearMonth</code>
              </td>
              <td>
                <code>VARCHAR</code> or <code>LONGVARCHAR</code>
              </td>
            </tr>
            <tr>
              <td>
                <code>JapaneseDateTypeHandler</code>
              </td>
              <td>
                <code>java.time.chrono.JapaneseDate</code>
              </td>
              <td>
                <code>DATE</code>
              </td>
            </tr>
          </tbody>
        </table>
        <p>
        Es posible sobrescribir los TypeHanders o crear TypeHanders personalizados para tratar tipos no soportados o no estándares.
        Para ello, debes implementar la interfaz <code>org.apache.ibatis.type.TypeHandler</code> o extender
        la clase de ayuda <code>org.apache.ibatis.type.BaseTypeHandler</code> y opcionalmente mapear el TypeHandler a un tipo JDBC.
        Por ejemplo:
        </p>

        <source><![CDATA[// ExampleTypeHandler.java
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ExampleTypeHandler extends BaseTypeHandler<String> {

  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
    ps.setString(i, parameter);
  }

  @Override
  public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
    return rs.getString(columnName);
  }

  @Override
  public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    return rs.getString(columnIndex);
  }

  @Override
  public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    return cs.getString(columnIndex);
  }
}
]]></source>

        <source><![CDATA[<!-- mybatis-config.xml -->
<typeHandlers>
  <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>
]]></source>

        <p>Al usar este TypeHandler se sobrescribe el TypeHandler existente para los tipos String y los parámetros y resultados VARCHAR. Observa que MyBatis no introspecciona la base de datos para conocer el tipo así que debes especificar que se trata de un VARCHAR en los mapeos de parámetros y resultados para que se use el TypeHandler adecuado. Esto se debe a que MyBatis no conoce nada sobre los tipos de datos hasta que la sentencia ha sido ejecutada.</p>
        <p>
          MyBatis conoce el tipo Java que quieres gestionar introspecionando tipo genérico del TypeHandler, pero puedes modificar este comportamiento de dos maneras.
        </p>
        <ul>
          <li>Añadir un atributo <code>javaType</code> al elemento typeHandler (por ejemplo: <code>javaType="String"</code>)
          </li>
          <li>Añadir una anotación <code>@MappedTypes</code> a tu clase TypeHandler especificando la lista de tipos java a la que asociarlo.
          Esta anotación será ignorada si se ha especificado también un atributo <code>javaType</code>.
          </li>
        </ul>


        <p>El tipo JDBC asociado se puede especificar de dos maneras:</p>
        <ul>
          <li>
           Añadiendo un atributo <code>jdbcType</code> al lemento typeHandler (por ejemplo: <code>jdbcType="VARCHAR"</code>).
          </li>
          <li>Añadiendo una anotación <code>@MappedJdbcTypes</code> a tu clase TypeHandler especificando la lista de tipos JDBC a la que asociarlo.
		   Esta anotación será ignorada si se ha especificado también un atributo <code>jdbcType</code>.
          </li>
        </ul>

        <p>
          When deciding which TypeHandler to use in a <code>ResultMap</code>, the Java type is known
          (from the result type), but the JDBC type is unknown. MyBatis therefore uses the combination
          <code>javaType=[TheJavaType], jdbcType=null</code> to choose a TypeHandler. This means that
          using a <code>@MappedJdbcTypes</code> annotation <i>restricts</i> the scope of a TypeHandler
          and makes it unavailable for use in <code>ResultMap</code>s unless explicity set. To make a
          TypeHandler available for use in a <code>ResultMap</code>, set <code>includeNullJdbcType=true</code>
          on the <code>@MappedJdbcTypes</code> annotation. Since Mybatis 3.4.0 however, if a <b>single</b>
          TypeHandler is registered to handle a Java type, it will be used by default in <code>ResultMap</code>s
          using this Java type (i.e. even without <code>includeNullJdbcType=true</code>).
        </p>

        <p>Y finalmente puedes hacer que MyBatis busque tus TypeHandlers:</p>
        <source><![CDATA[<!-- mybatis-config.xml -->
<typeHandlers>
  <package name="org.mybatis.example"/>
</typeHandlers>
]]></source>

        <p>
          Observa que cuando usas la función de búsqueda los tipos JDBC sólo se pueden especificar usando anotaciones.
        </p>

        <p>
          Puedes crear un TypeHandler genérico que sea capaz de manejar más de un tipo de clase. Para ello añade
          un constructor que recibe una clase como parámetro y MyBatis le pasará la clase actual cuando construya
          el TypeHandler.
        </p>

        <source><![CDATA[//GenericTypeHandler.java
public class GenericTypeHandler<E extends MyObject> extends BaseTypeHandler<E> {

  private Class<E> type;

  public GenericTypeHandler(Class<E> type) {
    if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
    this.type = type;
  }
  ...
]]></source>

		<p><code>EnumTypeHandler</code> y <code>EnumOrdinalTypeHandler</code> son TypeHandlers genéricos.
		Conoceremos más sobre ellos en la próxima sección.
		</p>

      </subsection>

      <subsection name="Handling Enums">
      	<p>
      	Si quires mapear un <code>Enum</code>, debes usar bien un
      	<code>EnumTypeHandler</code> o un <code>EnumOrdinalTypeHandler</code>.
      	</p>

      	<p>Por ejemplo, digamos que quieres guardar el modo de reondeo que debe
      	usarse con un número determinado que debe redondearse. Por defecto MyBatis
      	usa un <code>EnumTypeHandler</code> para comvertir los valores del  <code>Enum</code>
      	a sus nombres.
      	</p>

      	<b>Observa que el <code>EnumTypeHandler</code> es un handler especial en el sentido de que
      	no maneja una clase específica, como los demás handlers sino cualquier clase que extiende
      	de <code>Enum</code></b>

      	<p>
      	Sin embargo, puede que no queramos guardar nombres. Nuestro DBA puede insistir en que
      	usemos un entero en su lugar. Muy sencillo: añade un <code>EnumOrdinalTypeHandler</code>
      	a las sección de <code>typeHandlers</code> de tu fichero de configuración y ahora todos los
      	<code>RoundingMode</code> se mapearán a un entero usando su valor ordinal.
      	</p>
       <source><![CDATA[<!-- mybatis-config.xml -->
<typeHandlers>
  <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="java.math.RoundingMode"/>
</typeHandlers>
]]></source>
		<p>
		  Pero ¿y si quieres mapear el mismo <code>Enum</code> a un string en un sitio pero a un entero en otro?
		</p>
      	<p>
      	  El mapeo automático siempre usará <code>EnumOrdinalTypeHandler</code>,
      	  así que si queremos usar el clásico <code>EnumTypeHandler</code>,
      	  debemos indicarlo establiencidolo esplícitamente su uso en los statements.
      	</p>
      	<p>
      	  Los mappers no se tratarán hasta la sección siguiente asi que si esta es tu primera lectura de
      	  la documentación quizá prefieras saltarte esta sección por ahora y volver más tarde).
      	</p>
      	<source><![CDATA[<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.apache.ibatis.submitted.rounding.Mapper">
	<resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
		<result column="funkyNumber" property="funkyNumber"/>
		<result column="roundingMode" property="roundingMode"/>
	</resultMap>

	<select id="getUser" resultMap="usermap">
		select * from users
	</select>
	<insert id="insert">
	    insert into users (id, name, funkyNumber, roundingMode) values (
	    	#{id}, #{name}, #{funkyNumber}, #{roundingMode}
	    )
	</insert>

	<resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap2">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
		<result column="funkyNumber" property="funkyNumber"/>
		<result column="roundingMode" property="roundingMode" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
	</resultMap>
	<select id="getUser2" resultMap="usermap2">
		select * from users2
	</select>
	<insert id="insert2">
	    insert into users2 (id, name, funkyNumber, roundingMode) values (
	    	#{id}, #{name}, #{funkyNumber}, #{roundingMode, typeHandler=org.apache.ibatis.type.EnumTypeHandler}
	    )
	</insert>

</mapper>
]]></source>
		<p>
		  Observa que esto nos fuerza a usar un <code>resultMap</code>
		  en lugar de un <code>resultType</code> en nuestros statements tipo select.
		</p>
      </subsection>

      <subsection name="objectFactory">
        <p>Cada vez que MyBatis crea una nueva instancia de un objeto de resultado usa una instancia de ObjectFactory para hacerlo. El ObjectFactory por defecto no hace mucho más que instanciar la clase destino usando su constructor por defecto, o el constructor que se ha parametrizado en su caso. Es posible sobrescribir el comportamiento por defecto creando tu propio ObjectFactory. Por ejemplo:
        </p>
        <source><![CDATA[// ExampleObjectFactory.java
public class ExampleObjectFactory extends DefaultObjectFactory {
  public Object create(Class type) {
    return super.create(type);
  }
  public Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs) {
    return super.create(type, constructorArgTypes, constructorArgs);
  }
  public void setProperties(Properties properties) {
    super.setProperties(properties);
  }
  public <T> boolean isCollection(Class<T> type) {
    return Collection.class.isAssignableFrom(type);
  }
}]]></source>

        <source><![CDATA[<!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
  <property name="someProperty" value="100"/>
</objectFactory>]]></source>
        <p>La interfaz ObjectFactory es muy sencilla. Contiene solo dos métodos de creación, uno para el constructor por defecto y otro para el constructor parametrizado. Adicionalmente el método setProperties sirve para configurar el ObjectFactory. Las propiedades definidas en el cuerpo del elemento objectFactory se pasan al método setProperties después de que el ObjectFactory haya sido inicializado.
        </p>

      </subsection>
      <subsection name="plugins">
        <p>MyBatis permite interceptar las llamadas en ciertos puntos de la ejecución de un mapped statement. Por defecto, MyBatis permite incluir plugins que intercepten las llamadas de:
        </p>
        <ul>
          <li>
            Executor
            (update, query, flushStatements, commit, rollback,
            getTransaction, close,
            isClosed)
          </li>
          <li>
            ParameterHandler
            (getParameterObject, setParameters)
          </li>
          <li>
            ResultSetHandler
            (handleResultSets, handleOutputParameters)
          </li>
          <li>
            StatementHandler
            (prepare, parameterize, batch, update, query)
          </li>
        </ul>
        <p>Los detalles de estos métodos se pueden conocer observando sus firmas y el código fuente de los mismos que está disponible en el sitio de MyBatis. Es recomendable que comprendas el funcionamiento del método que estas sobrescribiendo siempre que vayas a hacer algo más complejo que monitorizar llamadas. Ten en cuenta que si modificas el comportamiento de alguno de estos métodos existe la posibilidad de que rompas el funcionamiento de MyBatis. Estas clases son de bajo nivel y por tanto debes usar los plugins con cuidado.
        </p>
        <p>Utilizar un plugin es muy sencillo para la potencia que ofrecen. Simplemente implementa el interfaz Interceptor y asegúrate de especificar las signaturas que quieres interceptar.
        </p>

        <source><![CDATA[// ExamplePlugin.java
@Intercepts({@Signature(
  type= Executor.class,
  method = "update",
  args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
  private Properties properties = new Properties();
  public Object intercept(Invocation invocation) throws Throwable {
    // implement pre processing if need
    Object returnObject = invocation.proceed();
    // implement post processing if need
    return returnObject;
  }
  public void setProperties(Properties properties) {
    this.properties = properties;
  }
}]]></source>

        <source><![CDATA[<!-- mybatis-config.xml -->
<plugins>
  <plugin interceptor="org.mybatis.example.ExamplePlugin">
    <property name="someProperty" value="100"/>
  </plugin>
</plugins>]]></source>
        <p>El plugin anterior interceptará cualquier llamada al método “update” en la instancia de Executor, que es un objeto interno que se encarga de la ejecución a bajo nivel de los mapped statements.
        </p>
        <p><span class="label important">NOTA</span>
          <strong>Acerca de sobrescribir la clase Configuration
          </strong>
        </p>
        <p>Además de modificar el comportamiento de MyBatis mediante los plugins, también es posible sobrescribir la clase Configuración por completo. Extiende la clase, sobrescribe sus métodos y pásala como parámetro en la llamada al método SqlSessionFactoryBuilder.build(myConfig). Nuevamente, ten cuenta que esto puede afectar seriamente al funcionamiento de MyBatis así que úsalo con cuidado.
        </p>
      </subsection>
      <subsection name="environments">
        <p>En MyBatis pueden configurarse varios entornos. De esta forma puedes usar tus SQL Maps en distintas bases de datos por muchos motivos. Por ejemplo puede que tengas una configuración distinta para tus entornos de desarrollo, pruebas y producción. O quizá tengas varias bases de datos en producción que comparten el esquema y quieres usar los mismos SQL maps sobre todas ellas. Como ves, hay muchos casos.
        </p>
        <p>
          <strong>Debes recordar un asunto importante. Cuando configures varios entornos, solo será posible usar UNO por cada instancia de SqlSessionFactory.</strong>
        </p>
        <p>Por lo tanto, si quieres conectar a dos bases de datos, deberás crear dos instancias de SqlSessionFactory, una para cada cual. Para el caso de tres bases de datos necesitarás tres instancias y así sucesivamente. Es fácil de recordar:
        </p>
        <ul>
          <li>
            <strong>Una instancia de SqlSessionFactory por base de datos</strong>
          </li>
        </ul>
        <p>Para indicar qué entorno debe utilizarse, debes informar el parámetro opcional correspondiente en la llamada al SqlSessionFactoryBuilder. Existen dos métodos que aceptan el entorno:</p>

        <source><![CDATA[SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment,properties);]]></source>

        <p>Si se omite el entorno se usará el entorno por defecto:</p>

        <source><![CDATA[SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader,properties);]]></source>

        <p>El elemento environments contiene la configuración del entorno:</p>

        <source><![CDATA[<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    <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>]]></source>
        <p>
          Observa que las secciones importantes son:
        </p>
        <ul>
          <li>El ID del entorno por defecto (ej. default=”development”).</li>
          <li>El ID de de cada entorno definido (ej. id=”development”).</li>
          <li>La configuración del TransactionManager (ej. type=”JDBC”)</li>
          <li>La configuración del DataSource (ej. type=”POOLED”)</li>
        </ul>
        <p>El ID del entorno por defecto y de los entornos existentes son auto-explicativos. Puedes nombrarlos como más te guste, tan sólo asegúrate de que el valor por defecto coincide con un entorno existente.
        </p>
        <p>
          <strong>transactionManager</strong>
        </p>
        <p>MyBatis incluye dos tipos de TransactionManager (ej. type=”[JDBC|MANAGED]”):
        </p>
        <ul>
          <li>JDBC – Este TransactionManager simplemente hace uso del las capacidades de commit y rollback de JDBC.  Utiliza la conexión obtenida del DataSource para gestionar la transacción.
          </li>
          <li>MANAGED  – Este TransactionManager no hace nada. No hace commit ni rollback sobre la conexión. En su lugar, permite que el contenedor gestione el ciclo de vida completo de la transacción (ej. Spring o un servidor de aplicaciones JEE).  Por defecto cierra la conexión. Sin embargo, algunos contenedores no esperan que la conexión se cierre y por tanto, si necesitas cambiar este comportamiento, informa la propiedad closeConnection a false. Por ejemplo:
<source><![CDATA[<transactionManager type="MANAGED">
  <property name="closeConnection" value="false"/>
</transactionManager>]]></source>
          </li>
        </ul>
        <p>
          <span class="label important">NOTA</span>
          Si estás pensando en usar MyBatis con Spring no necesitas configurar ningún TransactionManager
          porque el módulo de Spring configurará el suyo propio sobrescribiendo cualquier otra configuración previa.
        </p>
        <p>Ninguno de estos TransactionManagers necesita ninguna propiedad. Sin embargo ambos son Type Aliases, es decir, en lugar de usarlos puedes informar el nombre totalmente cualificado o el Type Alias de tu propia implementación del interfaz TransactionFactory:
        </p>
        <source><![CDATA[public interface TransactionFactory {
  default void setProperties(Properties props) { // Since 3.5.2, change to default method
    // NOP
  }
  Transaction newTransaction(Connection conn);
  Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}]]></source>
        <p>Todas las propiedades que configures en el XML se pasarán al método setProperties() tras la instanciación de la clase. Tu implementación debe crear una implementación de Transaction, que a su vez es también un interfaz muy sencillo:
        </p>
        <source><![CDATA[public interface Transaction {
  Connection getConnection() throws SQLException;
  void commit() throws SQLException;
  void rollback() throws SQLException;
  void close() throws SQLException;
  Integer getTimeout() throws SQLException;
}]]></source>
        <p>Con estos dos interfaces puedes personalizar por completo la forma en la que MyBatis gestiona las transacciones.</p>
        <p>
          <strong>dataSource</strong>
        </p>
        <p>El elemento dataSource sirve para configurar la forma de obtener conexiones JDBC mediante la interfaz DataSource JDBC estándar.</p>
        <ul>
          <li>La mayoría de las aplicaciones que usen MyBatis configurarán el dataSource como se muestra en el ejemplo. Sin embargo, esta configuración no es obligatoria. Ten en cuenta, aun así, que el dataSource es necesario para utilizar Lazy Loading.
          </li>
        </ul>
        <p>Hay tres tipos de dataSources pre-construidos (ej. type=”????”):</p>
        <p>
          <strong>UNPOOLED</strong> – Esta implementación de DataSource abre y cierra una conexión JDBC cada vez que se solcita una conexión. Aunque es un poco lento, es una buena elección para aplicaciones que no necesitan la velocidad de tener conexiones abiertas de forma inmediata. Las bases de datos tienen un rendimiento distinto en cuanto al rendimiento que aportan con este tipo de DataSource, para algunas de ellas no es muy importante tener un pool y por tanto esta configuración es apropiada. El DataSource UNPOOLED tiene las siguientes opciones de configuración:
          </p>
        <ul>
          <li><code>driver</code> – El nombre completamente cualificado de la clase java del driver JDBC (NO de la clase DataSource en el caso de que tu driver incluya una).</li>
          <li><code>url</code> – La URL de la instancia de base de datos.
          </li>
          <li><code>username</code> – El usuario de conexión.
          </li>
          <li><code>password</code> – La password de conexión.
          </li>
          <li><code>defaultTransactionIsolationLevel</code> – El nivel de aislamiento por defecto con el que se crearán las conexiones.
          </li>
          <li><code>defaultNetworkTimeout</code> – The default network timeout value in milliseconds to wait for the database operation to complete. See the API documentation of <code>java.sql.Connection#setNetworkTimeout()</code> for details.
          </li>
        </ul>
        <p>Opcionalmente, puedes también pasar propiedades al driver de la base de datos. Para ello prefija las propiedades con “driver.”, por ejemplo:
        </p>
        <ul>
          <li><code>driver.encoding=UTF8</code></li>
        </ul>
        <p>
          Esto pasaría la propiedad “encoding” con el valor “UTF8” al driver de base datos mediante el método DriverManager.getConnection(url, driverProperties).
        </p>
        <p>
          <strong>POOLED</strong> – Esta implementación de DataSource hace usa un pool de conexiones para evitar el tiempo necesario en realizar la conexión y autenticación cada vez que se solicita una nueva instancia de conexión. Este es un enfoque habitual en aplicaciones Web concurrentes para obtener el mejor tiempo de respuesta posible.</p>
        <p>Además de las propiedades de (UNPOOLED) hay otras muchas propiedades que se pueden usar para configurar el DataSource POOLED:
        </p>
        <ul>
          <li><code>poolMaximumActiveConnections</code> – Número máximo de conexiónes activas que pueden existir de forma simultánea. Por defecto:  10
          </li>
          <li><code>poolMaximumIdleConnections</code> – Número máximo de conexiones libres que pueden existir de forma simultánea.
          </li>
          <li><code>poolMaximumCheckoutTime</code> – Tiempo máximo que puede permanecer una conexión fuera del pool antes de que sea forzosamente devuelta. Por defecto: 20000ms (20 segundos)
          </li>
          <li><code>poolTimeToWait</code> – Este es un parámetro de bajo nivel que permite escribir un log y reintentar la adquisición de una conexión en caso de que no se haya conseguido la conexión transcurrido un tiempo razonable (esto evita que se produzcan fallos constantes y silenciosos si el pool está mal configurado). Por defecto:  20000ms (20 segundos)
          </li>
          <li><code>poolMaximumLocalBadConnectionTolerance</code> – This is a low level setting about
            tolerance of bad connections got for any thread. If a thread got a bad connection, it may
            still have another chance to re-attempt to get another connection which is valid. But the
            retrying times should not more than the sum of <code>poolMaximumIdleConnections</code>
            and <code>poolMaximumLocalBadConnectionTolerance</code>.
            Default:
            3 (Since: 3.4.5)
          </li>
          <li><code>poolPingQuery</code> – La query de ping (sondeo) que se envía a la base de datos para verificar que la conexión funciona correctamente y que está lista para aceptar nuevas peticiones de conexión. El valor por defecto es "NO PING QUERY SET", que hará que la mayoría de los drivers de base de datos devuelvan un error con un mensaje de error decente.
          </li>
          <li><code>poolPingEnabled</code> – Habilita o inhabilita la query de ping. Si está habilitada deberías informar también la propiedad poolPingQuery con una sentencia SQL (preferentemente una rápida).  Por defecto:  false.
          </li>
          <li><code>poolPingConnectionsNotUsedFor</code> – Configura la frecuencia con la que se ejecutará la sentencia poolPingQuery. Normalmente se iguala al timeout de la conexión de base de datos para evitar pings innecesarios. Por defecto: 0 (todas las conexiones se testean continuamente – solo si se ha habilitado poolPingEnabled).
          </li>
        </ul>
        <p>
          <strong>JNDI</strong>
          – Esta implementación de DataSource está pensada para ser usada en contenedores como Spring o los servidores de aplicaciones JEE en los que es posible configurar un DataSource de forma externa y alojarlo en el contexto JNDI. Esta configuración de DataSource requiere solo dos propiedades:
        </p>
        <ul>
          <li><code>initial_context</code> – Propiedad que se usa para realizar el lookup en el InitialContext (initialContext.lookup(initial_context)). Esta propiedad es opcional, si no se informa, se buscará directamente la propiedad data_source.
          </li>
          <li><code>data_source</code> – Es el contexto donde se debe buscar el DataSource. El DataSource se buscará en el contexto resultado de buscar data_source en el InitialContext o si no se ha informado la propiedad se buscará directamente sobre InitialContext.
          </li>
        </ul>
        <p>Al igual que en las otras configuraciones de DataSource. Es posible enviar propiedades directamente al InitialContext prefijando las propiedades con “env.”, por ejemplo:
        </p>
        <ul>
          <li><code>env.encoding=UTF8</code></li>
        </ul>
        <p>
         Enviará la propiedad “encoding” y el valor “UTF-8” al constructor del InitialContext durante su instanciación.
        </p>

		<p>
		  You can plug any 3rd party DataSource by implementing the interface <code>org.apache.ibatis.datasource.DataSourceFactory</code>:
		</p>

        <source><![CDATA[public interface DataSourceFactory {
  void setProperties(Properties props);
  DataSource getDataSource();
}]]></source>

        <p>
		  The <code>org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory</code> puede extenderse para crear nuevos
		  adaptadores. Por ejemplo, este es el código necesario para integrar C3P0:
		</p>

        <source><![CDATA[import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {

  public C3P0DataSourceFactory() {
    this.dataSource = new ComboPooledDataSource();
  }
}]]></source>

        <p>Para configurarlo, añade una propiedad por cada método al que quieres que llame MyBatis.
        A continuación se muestra una configuración de ejemplo para conectar con una base de datos PostgresSQL:</p>

        <source><![CDATA[<dataSource type="org.myproject.C3P0DataSourceFactory">
  <property name="driver" value="org.postgresql.Driver"/>
  <property name="url" value="jdbc:postgresql:mydb"/>
  <property name="username" value="postgres"/>
  <property name="password" value="root"/>
</dataSource>
]]></source>

      </subsection>

      <subsection name="databaseIdProvider">
        <p>
          MyBatis puede ejeutar sentencias distintas en función del fabricante (vendor) de tu base de datos.
          El soporte de múltiples bases de datos se basa en el atributo de <code>databaseId</code> de los mapped statements.
          MyBatis cargará todos los statements que no tengan atributo <code>databaseId</code> attribute o aquellos
          cuyo <code>databaseId</code> coincida con el valor en curso. Si se encuentra un statement con y sin atributo
          <code>databaseId</code> el último se descartará.
          Para activar el soporte de multi vendor añade un <code>databaseIdProvider</code>
          al fichero mybatis-config.xml file de la siguiente forma:
        </p>

        <source><![CDATA[<databaseIdProvider type="DB_VENDOR" />
]]></source>

		<p>
		  La implementación DB_VENDOR del databaseIdProvider establece como databaseId el String devuelto por
		  <code>DatabaseMetaData#getDatabaseProductName()</code>.
		  Como normalmente este string es demasiado largo, y además, distintas versiones del mismo producto devuelven valores
		  similares, puedes traducirlo a un valor más corto añadiendo propiedades de la siguente forma:
		</p>

        <source><![CDATA[<databaseIdProvider type="DB_VENDOR">
  <property name="SQL Server" value="sqlserver"/>
  <property name="DB2" value="db2"/>
  <property name="Oracle" value="oracle" />
</databaseIdProvider>]]></source>

		<p>
		  Cuando se añaden propiedades, el databaseIdProvider DB_VENDOR devuelve el primer valor que corresponde a la primera clave
		  encontrada en el nombre devuelto por <code>DatabaseMetaData#getDatabaseProductName()</code> o "null" si no se encuentra ninguna.
		  En este caso, si <code>getDatabaseProductName()</code> devuelve "Oracle (DataDirect)" el databaseId se informará con "oracle".
		</p>

		<p>
		  Puedes construir tu propio DatabaseIdProvider implementando la interfaz <code>org.apache.ibatis.mapping.DatabaseIdProvider</code>
		  y registrandolo en el fichero mybatis-config.xml:
		</p>

        <source><![CDATA[public interface DatabaseIdProvider {
  default void setProperties(Properties p) { // Since 3.5.2, change to default method
    // NOP
  }
  String getDatabaseId(DataSource dataSource) throws SQLException;
}]]></source>

      </subsection>

      <subsection name="mappers">
        <p>
          Ahora que se ha configurado el comportamiento de MyBatis con todos los elementos de configuración comentados estamos listos para definir los SQL mapped statements (sentencias SQL mapeadas). Primeramente necesitaremos indicarle a MyBatis dónde encontrarlos. Java no ofrece muchas posibilidades de auto-descubrimiento así que la mejor forma es simplemente decirle a MyBatis donde encontrar los ficheros de mapeo. Puedes utilizar referencias tipo classpath, o tipo path o referencias url completamente cualificadas (incluyendo file:///) . Por ejemplo:
        </p>
        <source><![CDATA[<!-- Using classpath relative resources -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>]]></source>

        <source><![CDATA[<!-- Using url fully qualified paths -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>]]></source>

        <source><![CDATA[<!-- Using mapper interface classes -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>]]></source>

        <source><![CDATA[<!-- Register all interfaces in a package as mappers -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>]]></source>

        <p>
         Esta configuración sólo indica a MyBatis cuáles son los ficheros de mapeo. El resto de la configuración se encuentra dentro de estos ficheros, y eso es de lo que hablaremos en el siguiente apartado.
        </p>
      </subsection>
    </section>
  </body>
</document>
