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 }