<?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-Spring | SqlSessionFactoryBean</title>
    <author email="hpresnall@gmail.com">Hunter Presnall</author>
    <author email="eduardo.macarron@gmail.com">Eduardo Macarron</author>
    <author email="nanlei1987@gmail.com">Nan Lei</author>
  </properties>

  <body>
    <section name="SqlSessionFactoryBean">
      <p>
      在基础的 MyBatis 用法中，是通过 <code>SqlSessionFactoryBuilder</code> 来创建 <code>SqlSessionFactory</code> 的。
      而在 MyBatis-Spring 中，则使用 <code>SqlSessionFactoryBean</code> 来创建。
      </p>
      
    <subsection name="设置">
      <p>
      要创建工厂 bean，将下面的代码放到 Spring 的 XML 配置文件中：
      </p>
        <source><![CDATA[
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
</bean>]]></source>

<p>
  需要注意的是 <code>SqlSessionFactoryBean</code> 实现了 Spring 的 <code>FactoryBean</code> 接口（参见 Spring 官方文档 3.8 节 <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-extension-factorybean">通过工厂 bean 自定义实例化逻辑</a>）。这意味着由 Spring 最终创建的 bean <b>并不是</b> <code>SqlSessionFactoryBean</code> 本身，而是工厂类（<code>SqlSessionFactoryBean</code>）的 getObject() 方法的返回结果。这种情况下，Spring 将会在应用启动时为你创建 <code>SqlSessionFactory</code>，并使用 <code>sqlSessionFactory</code> 这个名字存储起来。
</p>
<p>
  等效的 Java 代码如下：
</p>

      <source><![CDATA[
@Bean
public SqlSessionFactory sqlSessionFactory() {
  SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
  factoryBean.setDataSource(dataSource());
  return factoryBean.getObject();
}]]></source>

      <p>
        通常，在 MyBatis-Spring 中，你不需要直接使用 <code>SqlSessionFactoryBean</code> 或对应的 <code>SqlSessionFactory</code>。相反，session 的工厂 bean 将会被注入到 <code>MapperFactoryBean</code> 或其它继承于 <code>SqlSessionDaoSupport</code> 的 DAO（Data Access Object，数据访问对象）中。
      </p>
    </subsection>

    <subsection name="属性">

      <p>
        <code>SqlSessionFactory</code> 有一个唯一的必要属性：用于 JDBC 的 <code>DataSource</code>。这可以是任意的 <code>DataSource</code> 对象，它的配置方法和其它 Spring 数据库连接是一样的。
      </p>

      <p>
        一个常用的属性是 <code>configLocation</code>，它用来指定 MyBatis 的 XML 配置文件路径。它在需要修改 MyBatis 的基础配置非常有用。通常，基础配置指的是 <code>&lt;settings&gt;</code> 或 <code>&lt;typeAliases&gt;</code> 元素。
      </p>

      <p>
        需要注意的是，这个配置文件<b>并不需要</b>是一个完整的 MyBatis 配置。确切地说，任何环境配置（<code>&lt;environments&gt;</code>），数据源（<code>&lt;DataSource&gt;</code>）和 MyBatis 的事务管理器（<code>&lt;transactionManager&gt;</code>）都会被<b>忽略</b>。<code>SqlSessionFactoryBean</code> 会创建它自有的 MyBatis 环境配置（<code>Environment</code>），并按要求设置自定义环境的值。
      </p>

      <p>
        如果 MyBatis 在映射器类对应的路径下找不到与之相对应的映射器 XML 文件，那么也需要配置文件。这时有两种解决办法：第一种是手动在 MyBatis 的 XML 配置文件中的 &lt;mappers&gt; 部分中指定 XML 文件的类路径；第二种是设置工厂 bean 的 <code>mapperLocations</code> 属性。
      </p>

      <p>
        <code>mapperLocations</code> 属性接受多个资源位置。这个属性可以用来指定 MyBatis 的映射器 XML 配置文件的位置。属性的值是一个 Ant 风格的字符串，可以指定加载一个目录中的所有文件，或者从一个目录开始递归搜索所有目录。比如:
      </p>
      
        <source><![CDATA[
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />
</bean>]]></source>

      <p>
        这会从类路径下加载所有在 sample.config.mappers 包和它的子包中的 MyBatis 映射器 XML 配置文件。
      </p>

      <p>
        在容器管理事务的时候，你可能需要的一个属性是 <code>transactionFactoryClass</code>。请参考事务一章的相关章节。
      </p>

      <p>
        如果你使用了多个数据库，那么需要设置 <code>databaseIdProvider</code> 属性：
      </p>

      <source><![CDATA[
<bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
  <property name="properties">
    <props>
      <prop key="SQL Server">sqlserver</prop>
      <prop key="DB2">db2</prop>
      <prop key="Oracle">oracle</prop>
      <prop key="MySQL">mysql</prop>
    </props>
  </property>
</bean>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />
  <property name="databaseIdProvider" ref="databaseIdProvider"/>
</bean>]]></source>

        <p>
          <span class="label important">提示</span> 自 1.3.0 版本开始，新增的 <code>configuration</code> 属性能够在没有对应的 MyBatis XML 配置文件的情况下，直接设置 <code>Configuration</code> 实例。例如：
        </p>

        <source><![CDATA[
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="configuration">
    <bean class="org.apache.ibatis.session.Configuration">
      <property name="mapUnderscoreToCamelCase" value="true"/>
    </bean>
  </property>
</bean>]]></source>

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