View Javadoc
1   /*
2    * Copyright 2010-2022 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  
18  import static org.springframework.util.Assert.notNull;
19  
20  import org.apache.ibatis.executor.ErrorContext;
21  import org.apache.ibatis.session.Configuration;
22  import org.mybatis.spring.SqlSessionTemplate;
23  import org.mybatis.spring.support.SqlSessionDaoSupport;
24  import org.springframework.beans.factory.FactoryBean;
25  
26  /**
27   * BeanFactory that enables injection of MyBatis mapper interfaces. It can be set up with a SqlSessionFactory or a
28   * pre-configured SqlSessionTemplate.
29   * <p>
30   * Sample configuration:
31   *
32   * <pre class="code">
33   * {@code
34   *   <bean id="baseMapper" class="org.mybatis.spring.mapper.MapperFactoryBean" abstract="true" lazy-init="true">
35   *     <property name="sqlSessionFactory" ref="sqlSessionFactory" />
36   *   </bean>
37   *
38   *   <bean id="oneMapper" parent="baseMapper">
39   *     <property name="mapperInterface" value="my.package.MyMapperInterface" />
40   *   </bean>
41   *
42   *   <bean id="anotherMapper" parent="baseMapper">
43   *     <property name="mapperInterface" value="my.package.MyAnotherMapperInterface" />
44   *   </bean>
45   * }
46   * </pre>
47   * <p>
48   * Note that this factory can only inject <em>interfaces</em>, not concrete classes.
49   *
50   * @author Eduardo Macarron
51   *
52   * @see SqlSessionTemplate
53   */
54  public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
55  
56    private Class<T> mapperInterface;
57  
58    private boolean addToConfig = true;
59  
60    public MapperFactoryBean() {
61      // intentionally empty
62    }
63  
64    public MapperFactoryBean(Class<T> mapperInterface) {
65      this.mapperInterface = mapperInterface;
66    }
67  
68    /**
69     * {@inheritDoc}
70     */
71    @Override
72    protected void checkDaoConfig() {
73      super.checkDaoConfig();
74  
75      notNull(this.mapperInterface, "Property 'mapperInterface' is required");
76  
77      Configuration configuration = getSqlSession().getConfiguration();
78      if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
79        try {
80          configuration.addMapper(this.mapperInterface);
81        } catch (Exception e) {
82          logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", e);
83          throw new IllegalArgumentException(e);
84        } finally {
85          ErrorContext.instance().reset();
86        }
87      }
88    }
89  
90    /**
91     * {@inheritDoc}
92     */
93    @Override
94    public T getObject() throws Exception {
95      return getSqlSession().getMapper(this.mapperInterface);
96    }
97  
98    /**
99     * {@inheritDoc}
100    */
101   @Override
102   public Class<T> getObjectType() {
103     return this.mapperInterface;
104   }
105 
106   /**
107    * {@inheritDoc}
108    */
109   @Override
110   public boolean isSingleton() {
111     return true;
112   }
113 
114   // ------------- mutators --------------
115 
116   /**
117    * Sets the mapper interface of the MyBatis mapper
118    *
119    * @param mapperInterface
120    *          class of the interface
121    */
122   public void setMapperInterface(Class<T> mapperInterface) {
123     this.mapperInterface = mapperInterface;
124   }
125 
126   /**
127    * Return the mapper interface of the MyBatis mapper
128    *
129    * @return class of the interface
130    */
131   public Class<T> getMapperInterface() {
132     return mapperInterface;
133   }
134 
135   /**
136    * If addToConfig is false the mapper will not be added to MyBatis. This means it must have been included in
137    * mybatis-config.xml.
138    * <p>
139    * If it is true, the mapper will be added to MyBatis in the case it is not already registered.
140    * <p>
141    * By default addToConfig is true.
142    *
143    * @param addToConfig
144    *          a flag that whether add mapper to MyBatis or not
145    */
146   public void setAddToConfig(boolean addToConfig) {
147     this.addToConfig = addToConfig;
148   }
149 
150   /**
151    * Return the flag for addition into MyBatis config.
152    *
153    * @return true if the mapper will be added to MyBatis in the case it is not already registered.
154    */
155   public boolean isAddToConfig() {
156     return addToConfig;
157   }
158 }