<?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 | Injecting Mappers</title>
    <author email="hpresnall@gmail.com">Hunter Presnall</author>
    <author email="eduardo.macarron@gmail.com">Eduardo Macarron</author>
  </properties>

  <body>
    <section name="Injecting Mappers">
      <p>
        Rather than code data access objects (DAOs) manually using
        <code>SqlSessionDaoSupport</code> or
        <code>SqlSessionTemplate</code>, Mybatis-Spring can create a 
        thread safe mapper that you can inject directly into other beans:
      </p>

      <source><![CDATA[<bean id="fooService" class="org.mybatis.spring.sample.service.FooServiceImpl">
  <constructor-arg ref="userMapper" />
</bean>]]></source>
 
      <p>
         Once injected, the mapper is ready to be used in application logic:
      </p>
         <source><![CDATA[public class FooServiceImpl implements FooService {

  private final UserMapper userMapper;

  public FooServiceImpl(UserMapper userMapper) {
    this.userMapper = userMapper;
  }

  public User doSomeBusinessStuff(String userId) {
    return this.userMapper.getUser(userId);
  }
}]]></source>
       <p>
         Notice that there are no <code>SqlSession</code> or MyBatis
         references in this code. Nor is there any need to create, open or close
         the session, MyBatis-Spring will take care of that.
       </p>

	<subsection name="Registering a mapper" id="register">
	  <p>
	    The way you register a mapper depends on whether you are using a classic XML configuration
	    or the new 3.0+ Java Config (a.k.a. @Configuration).</p>
	
      <h4>With XML Config</h4>
      
      <p>
        A mapper is registered to Spring by including a <code>MapperFactoryBean</code> in your XML
        config file like follows: 
      </p>
        <source><![CDATA[<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>]]></source>

      <p>
        If the UserMapper has a corresponding MyBatis XML mapper file 
        in the same classpath location as the mapper interface, it will be
        parsed automatically by the <code>MapperFactoryBean</code>. There
        is no need to specify the mapper in a MyBatis configuration file unless
        the mapper XML files are in a different classpath location. See the
        <code>SqlSessionFactoryBean's</code>
        <code><a href="factorybean.html">configLocation</a></code>
        property for more information.
      </p>

      <p>
        Note that <code>MapperFactoryBean</code> requires either an
        <code>SqlSessionFactory</code> or an <code>SqlSessionTemplate</code>.
        These can be set through the respective <code>sqlSessionFactory</code> and
        <code>sqlSessionTemplate</code> properties.
        If both properties are set, the <code>SqlSessionFactory</code> is ignored.
        Since the <code>SqlSessionTemplate</code> is required to have a session
        factory set, that factory will be used by <code>MapperFactoryBean</code>.
      </p>
      
       <h4>With Java Config</h4>

    <source><![CDATA[
@Bean
public MapperFactoryBean<UserMapper> userMapper() throws Exception {
  MapperFactoryBean<UserMapper> factoryBean = new MapperFactoryBean<>(UserMapper.class);
  factoryBean.setSqlSessionFactory(sqlSessionFactory());
  return factoryBean;
}]]></source>
    </subsection>

    <subsection name="Scanning for mappers" id="scan">
      <p>
        There is no need to register all your mappers one by one.
        Instead, you can let MyBatis-Spring scan your classpath for them.
      </p>
      
      <p>
        There are three different ways to do it:
      </p>
      <ul>
        <li>Using the <code>&lt;mybatis:scan/&gt;</code> element.</li>
        <li>Using the annotation <code>@MapperScan</code></li>
        <li>Using a classic Spring xml file and registering the <code>MapperScannerConfigurer</code></li>
      </ul>
      
      <p>Both <code>&lt;mybatis:scan/&gt;</code> and <code>@MapperScan</code> are features introduced in MyBatis-Spring 1.2.0.
      <code>@MapperScan</code> requires Spring 3.1+.</p>

      <p>
        Since 2.0.2, mapper scanning feature support a option (<code>lazy-initialization</code>)
        that control lazy initialization enabled/disabled of mapper bean.
        The motivation for adding this option is supporting a lazy initialization control feature supported by Spring Boot 2.2.
        The default of this option is <code>false</code> (= not use lazy initialization).
        If developer want to use lazy initialization for mapper bean, it should be set to the <code>true</code> expressly.
      </p>
      <p>
        <span class="label important">IMPORTANT</span> If use the lazy initialization feature,
        the developer need to understand following limitations. If any of following conditions are matches,
        usually the lazy initialization feature cannot use on your application.
      </p>
      <ul>
        <li>When refers to the statement of <b>other mapper</b> using <code><![CDATA[<association>]]></code>(<code>@One</code>) and <code><![CDATA[<collection>]]></code>(<code>@Many</code>)</li>
        <li>When includes to the fragment of <b>other mapper</b> using <code><![CDATA[<include>]]></code></li>
        <li>When refers to the cache of <b>other mapper</b> using <code><![CDATA[<cache-ref>]]></code>(<code>@CacheNamespaceRef</code>)</li>
        <li>When refers to the result mapping of <b>other mapper</b> using <code><![CDATA[<select resultMap="...">]]></code>(<code>@ResultMap</code>)</li>
      </ul>

      <p>
        <span class="label important">NOTE</span> However, It become possible to use it by simultaneously initializing dependent beans using <code>@DependsOn</code>(Spring's feature) as follow:
      </p>

      <source><![CDATA[@DependsOn("vendorMapper")
public interface GoodsMapper {
  // ...
}]]></source>

      <h4>&lt;mybatis:scan/&gt;</h4>
      
      <p>
        The <code>&lt;mybatis:scan/&gt;</code> XML element will search for mappers 
        in a very similar way than the Spring built-in element <code>&lt;context:component-scan/&gt;</code>
        searches for beans. 
      </p>
      
      <p>Follows below a sample XML configuration:</p>

        <source><![CDATA[<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
  xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">

  <mybatis:scan base-package="org.mybatis.spring.sample.mapper" />

  <!-- ... -->

</beans>]]></source>

      <p>
        The <code>base-package</code> attribute lets you set the base package
        for your mapper interface files. You can set more than one package by
        using a semicolon or comma as a separator. Mappers will be searched for
        recursively starting in the specified package(s).
      </p>

      <p>
        Notice that there is no need to specify a <code>SqlSessionFactory</code> or
        <code>SqlSessionTemplate</code> as an attribute in the <code>&lt;mybatis:scan/&gt;</code>
        element because it will create <code>MapperFactoryBean</code>s that can be autowired. 
        But if you are using more than one <code>DataSource</code> autowire may not work for you. 
        In this case you can use the <code>factory-ref</code> or
        <code>template-ref</code> attributes to set the right bean name to use.
      </p>

      <p>
        <code>&lt;mybatis:scan/&gt;</code> supports filtering the mappers
        created by either specifying a marker interface or an annotation. The
        <code>annotation</code> property specifies an annotation to
        search for. The <code>marker-interface</code> attribute specifies a
        parent interface to search for. If both properties are specified, mappers
        are added for interfaces that match <strong>either</strong> criteria.
        By default, these two properties are null, so all interfaces in the given
        base package(s) will be loaded as mappers.
      </p>

      <p>
        Discovered mappers will be named using Spring default naming strategy for
        autodetected components (see <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-scanning-name-generator">the Spring reference document(Core Technologies -Naming autodetected components-)</a>).
        That is, if no annotation is found, it will use the uncapitalized non-qualified class
        name of the mapper. But if either a @Component or a JSR-330 @Named annotation is
        found it will get the name from the annotation.
        Notice that you can set the <code>annotation</code> attribute
        to <code>org.springframework.stereotype.Component</code>,
        <code>javax.inject.Named</code> (if you have JSE 6) or to your own annotation
        (that must be itself annotated) so the annotation will work both as a marker
        and as a name provider.
      </p>

      <p>
        <span class="label important">NOTE</span> <code>&lt;context:component-scan/&gt;</code> 
        won't be able to scan and register mappers. Mappers are interfaces and, in order to register them to 
        Spring, the scanner must know how to create a <code>MapperFactoryBean</code> for each interface
        it finds. 
      </p>

      <h4>@MapperScan</h4>
      
      <p>
        If you are using the Spring Java Configuration (a.k.a @Configuration) you would 
        prefer to use the <code>@MapperScan</code> rather than the 
        <code>&lt;mybatis:scan/&gt;</code>.  
      </p>
      
      <p>The <code>@MapperScan</code> annotation is used as follows:</p>
   
   <source><![CDATA[@Configuration
@MapperScan("org.mybatis.spring.sample.mapper")
public class AppConfig {
  // ...
}
]]></source>
	
	  <p>The annotation works in the same exact way than <code>&lt;mybatis:scan/&gt;</code> we
	  saw in the previous section. It also lets you specify a marker interface or an annotation class
	  through its properties <code>markerInterface</code> and <code>annotationClass</code>. 
	  You can also provide an specific <code>SqlSessionFactory</code> or <code>SqlSessionTemplate</code>
	  by using its properties <code>sqlSessionFactory</code> and <code>sqlSessionTemplate</code>.
	  </p>
     
      <h4>MapperScannerConfigurer</h4>
        
      <p>
        The <code>MapperScannerConfigurer</code> is a <code>BeanDefinitionRegistryPostProcessor</code> that
        can be included in a classic xml application context as a normal bean.
        To set up a <code>MapperScannerConfigurer</code> add the following to the Spring configuration:
      </p>
        <source><![CDATA[<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="org.mybatis.spring.sample.mapper" />
</bean>]]></source>

      <p>
        If you need to specify an specific <code>sqlSessionFactory</code> or <code>sqlSessionTemplate</code>
        note that <strong>bean names</strong> are required,
        not bean references, thus the <code>value</code> attribute is used instead of the
        usual <code>ref</code>:
      </p>
      <source><![CDATA[<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />]]></source>
    
      <p>
        <span class="label important">NOTE</span> <code>sqlSessionFactoryBean</code> and 
        <code>sqlSessionTemplateBean</code> properties were the only option available up to MyBatis-Spring 1.0.2 
        but given that the <code>MapperScannerConfigurer</code> runs earlier in the startup 
        process that <code>PropertyPlaceholderConfigurer</code> there were frequent errors. 
        For that purpose that properties have been deprecated and the new properties 
        <code>sqlSessionFactoryBeanName</code> and <code>sqlSessionTemplateBeanName</code> 
        are recommended.
      </p>
      </subsection>
    </section>
  </body>
</document>
