MapperFactoryBean.java

  1. /*
  2.  * Copyright 2010-2024 the original author or authors.
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *    https://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. package org.mybatis.spring.mapper;

  17. import static org.springframework.util.Assert.notNull;

  18. import org.apache.ibatis.executor.ErrorContext;
  19. import org.mybatis.spring.SqlSessionTemplate;
  20. import org.mybatis.spring.support.SqlSessionDaoSupport;
  21. import org.springframework.beans.factory.FactoryBean;

  22. /**
  23.  * BeanFactory that enables injection of MyBatis mapper interfaces. It can be set up with a SqlSessionFactory or a
  24.  * pre-configured SqlSessionTemplate.
  25.  * <p>
  26.  * Sample configuration:
  27.  *
  28.  * <pre class="code">
  29.  * {@code
  30.  *   <bean id="baseMapper" class="org.mybatis.spring.mapper.MapperFactoryBean" abstract="true" lazy-init="true">
  31.  *     <property name="sqlSessionFactory" ref="sqlSessionFactory" />
  32.  *   </bean>
  33.  *
  34.  *   <bean id="oneMapper" parent="baseMapper">
  35.  *     <property name="mapperInterface" value="my.package.MyMapperInterface" />
  36.  *   </bean>
  37.  *
  38.  *   <bean id="anotherMapper" parent="baseMapper">
  39.  *     <property name="mapperInterface" value="my.package.MyAnotherMapperInterface" />
  40.  *   </bean>
  41.  * }
  42.  * </pre>
  43.  * <p>
  44.  * Note that this factory can only inject <em>interfaces</em>, not concrete classes.
  45.  *
  46.  * @author Eduardo Macarron
  47.  *
  48.  * @see SqlSessionTemplate
  49.  */
  50. public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {

  51.   private Class<T> mapperInterface;

  52.   private boolean addToConfig = true;

  53.   public MapperFactoryBean() {
  54.     // intentionally empty
  55.   }

  56.   public MapperFactoryBean(Class<T> mapperInterface) {
  57.     this.mapperInterface = mapperInterface;
  58.   }

  59.   @Override
  60.   protected void checkDaoConfig() {
  61.     super.checkDaoConfig();

  62.     notNull(this.mapperInterface, "Property 'mapperInterface' is required");

  63.     var configuration = getSqlSession().getConfiguration();
  64.     if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
  65.       try {
  66.         configuration.addMapper(this.mapperInterface);
  67.       } catch (Exception e) {
  68.         logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", e);
  69.         throw new IllegalArgumentException(e);
  70.       } finally {
  71.         ErrorContext.instance().reset();
  72.       }
  73.     }
  74.   }

  75.   @Override
  76.   public T getObject() throws Exception {
  77.     return getSqlSession().getMapper(this.mapperInterface);
  78.   }

  79.   @Override
  80.   public Class<T> getObjectType() {
  81.     return this.mapperInterface;
  82.   }

  83.   @Override
  84.   public boolean isSingleton() {
  85.     return true;
  86.   }

  87.   // ------------- mutators --------------

  88.   /**
  89.    * Sets the mapper interface of the MyBatis mapper
  90.    *
  91.    * @param mapperInterface
  92.    *          class of the interface
  93.    */
  94.   public void setMapperInterface(Class<T> mapperInterface) {
  95.     this.mapperInterface = mapperInterface;
  96.   }

  97.   /**
  98.    * Return the mapper interface of the MyBatis mapper
  99.    *
  100.    * @return class of the interface
  101.    */
  102.   public Class<T> getMapperInterface() {
  103.     return mapperInterface;
  104.   }

  105.   /**
  106.    * If addToConfig is false the mapper will not be added to MyBatis. This means it must have been included in
  107.    * mybatis-config.xml.
  108.    * <p>
  109.    * If it is true, the mapper will be added to MyBatis in the case it is not already registered.
  110.    * <p>
  111.    * By default addToConfig is true.
  112.    *
  113.    * @param addToConfig
  114.    *          a flag that whether add mapper to MyBatis or not
  115.    */
  116.   public void setAddToConfig(boolean addToConfig) {
  117.     this.addToConfig = addToConfig;
  118.   }

  119.   /**
  120.    * Return the flag for addition into MyBatis config.
  121.    *
  122.    * @return true if the mapper will be added to MyBatis in the case it is not already registered.
  123.    */
  124.   public boolean isAddToConfig() {
  125.     return addToConfig;
  126.   }
  127. }