spring-mybatis與原生mybatis使用對比分析
原生mybatis使用方法:
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
try {
Employee employee = new Employee(null, "doubi", "1", "ddd@sys.com");
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
mapper.addEmp(employee);
session.commit();
} finally {
session.close();
}
spring使用方法,直接注入即可
@Autowired EmployeeMapper employeeMapper
那么spring為我們做了什么?下面研究一下mybatis-spring.jar這個jar包
首先來看一下如何使用spring整合mybatis,下面是使用spring-mybatis的四種方法:
方法一:(使用MapperFactoryBean)
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"></property> <!-- 自動掃描mapping.xml文件 --> <property name="mapperLocations" value="classpath:mapper/*.xml"></property> </bean> <!--上面生成sqlSessionFactory的幾個方法基本相同--> <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>
這樣做的缺點是每一個mapper接口都要在xml里配置一下
方法二:采用接口org.apache.ibatis.session.SqlSession的實現(xiàn)類 org.mybatis.spring.SqlSessionTemplate
mybatis中, sessionFactory可由SqlSessionFactoryBuilder.來創(chuàng)建。MyBatis-Spring 中,使用了SqlSessionFactoryBean來替代。SqlSessionFactoryBean有一個必須屬性dataSource,另外其還有一個通用屬性configLocation(用來指定mybatis的xml配置文件路徑)。
SqlSessionFactoryBean即相當(dāng)于原生mybatis中的SqlSessionFactoryBuilder
<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:sqlMapConfig.xml"/>
<!-- 自動掃描mapping.xml文件,**表示迭代查找,也可在sqlMapConfig.xml中單獨指定xml文件-->
<property name="mapperLocations" value="classpath:com/hua/saf/**/*.xml" />
</bean>
<!-- mybatis spring sqlSessionTemplate,使用時直接讓spring注入即可 -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
//使用方法:
@Repositorypublic class UserDao{ @Resource private SqlSessionTemplate sqlSessionTemplate; public User getUser(int id) { return sqlSessionTemplate.selectOne(this.getClass().getName() + ".getUser", 1); } }
為什么可以這樣寫,來看一下SqlSessionTemplate
public class SqlSessionTemplate implements SqlSession { private final SqlSessionFactory sqlSessionFactory; private final ExecutorType executorType; private final SqlSession sqlSessionProxy; private final PersistenceExceptionTranslator exceptionTranslator; /** * Constructs a Spring managed SqlSession with the {@code SqlSessionFactory} * provided as an argument. * * @param sqlSessionFactory */ public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType()); }
........省略......
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); notNull(executorType, "Property 'executorType' is required"); this.sqlSessionFactory = sqlSessionFactory; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; this.sqlSessionProxy = (SqlSession) newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor()); }
}
如上面代碼所示,SqlSessionTemplate類實現(xiàn)了原生Mybatis中的SqlSession接口,實際上它就是原生mybatis中的SqlSession
方法三:采用抽象類 org.mybatis.spring.support.SqlSessionDaoSupport 提供SqlSession
<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:sqlMapConfig.xml"/>
<!-- 自動掃描mapping.xml文件,**表示迭代查找,也可在sqlMapConfig.xml中單獨指定xml文件-->
<property name="mapperLocations" value="classpath:com/hua/saf/**/*.xml" />
</bean>
public class BaseDao extends SqlSessionDaoSupport{ //使用sqlSessionFactory @Autowired private SqlSessionFactory sqlSessionFactory;
@Autowired public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory)
{
super.setSqlSessionFactory(sqlSessionFactory);
} /** * 執(zhí)行insert操作 * @param statement * @return */ public int insert(String statement) {
return getSqlSession().insert(statement); } /** * 執(zhí)行insert操作 * @param statement * @param parameter * @return */ public int insert(String statement, Object parameter) {
return getSqlSession().insert(statement, parameter); }
public int update(String statement)
{ return getSqlSession().update(statement);
}
public int update(String statement, Object parameter) { return getSqlSession().update(statement, parameter); }
public int delete(String statement)
{
return getSqlSession().delete(statement);
}
public int delete(String statement, Object parameter) {
return getSqlSession().delete(statement, parameter); } /** * 獲取一個list集合 * @param statement * @return */ public List<?> selectList(String statement) { return getSqlSession().selectList(statement); } /** * 根據(jù)參數(shù) 獲取一個list集合 * @param statement * @param parameter * @return */ public List<?> selectList(String statement, Object parameter) { return getSqlSession().selectList(statement, parameter); } public Map<?, ?> selectMap(String statement, String mapKey) { return getSqlSession().selectMap(statement, mapKey); } public Map<?, ?> selectMap(String statement, Object parameter, String mapKey) { return getSqlSession().selectMap(statement, parameter, mapKey); } /** * 獲取Object對象 * @param statement * @return */ public Object selectOne(String statement) { return getSqlSession().selectOne(statement); } /** * 獲取connection, 以便執(zhí)行較為復(fù)雜的用法 * @return */ public Connection getConnection() { return getSqlSession().getConnection(); } }
如上代碼,一個Dao類繼承了SqlSessionDaoSupport類后,就可以在類中注入SessionFact
ory,進(jìn)而通過getSqlSession()獲取當(dāng)前SqlSession
下面是 SqlSessionDaoSupport的源碼 ,它是一個抽象類,并擁有sqlSession屬性,在setSqlSessionFactory方法中實例化了該sqlSession:
public abstract class SqlSessionDaoSupport extends DaoSupport
{
private SqlSession sqlSession; private boolean externalSqlSession;
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory)
{
if (!this.externalSqlSession) {
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
{
this.sqlSession = sqlSessionTemplate; this.externalSqlSession = true;
}
public SqlSession getSqlSession()
{
return this.sqlSession;
}
protected void checkDaoConfig()
{
notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required"); }}
方法四:(也是 最常見的使用方法 ,使用MapperScannerConfigurer,它將會查找類路徑下的映射器并自動將它們創(chuàng)建成MapperFactoryBean)
由于直接使用MapperFactoryBean會在配置文件中配置大量mapper,因此這里使用包掃描的方式通過注解獲取該bean
<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自動掃描mapping.xml文件,**表示迭代查找 -->
<property name="mapperLocations" value="classpath:com/hua/saf/**/*.xml" />
</bean>
<!-- DAO接口所在包名,Spring會自動查找其下的類 ,包下的類需要使用@MapperScan注解,否則容器注入會失敗 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.hua.saf.*" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
//使用如下代碼,即可完成注入
@Resource
private UserDao userDao;
下面看一下MapperScannerConfigurer這個類:
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware { private String basePackage; private boolean addToConfig = true; private SqlSessionFactory sqlSessionFactory; private SqlSessionTemplate sqlSessionTemplate; private String sqlSessionFactoryBeanName; private String sqlSessionTemplateBeanName; private Class<? extends Annotation> annotationClass; private Class<?> markerInterface; private ApplicationContext applicationContext; private String beanName; private boolean processPropertyPlaceHolders; private BeanNameGenerator nameGenerator;
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { if (this.processPropertyPlaceHolders) { processPropertyPlaceHolders(); } ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); scanner.setAddToConfig(this.addToConfig); scanner.setAnnotationClass(this.annotationClass); scanner.setMarkerInterface(this.markerInterface); scanner.setSqlSessionFactory(this.sqlSessionFactory); scanner.setSqlSessionTemplate(this.sqlSessionTemplate); scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName); scanner.setResourceLoader(this.applicationContext); scanner.setBeanNameGenerator(this.nameGenerator); scanner.registerFilters(); scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); }
ClassPathMapperScanner :
public Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); } else { for (BeanDefinitionHolder holder : beanDefinitions) { GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition(); if (logger.isDebugEnabled()) { logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface"); } // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName()); definition.setBeanClass(MapperFactoryBean.class); definition.getPropertyValues().add("addToConfig", this.addToConfig); boolean explicitFactoryUsed = false; if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) { definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionFactory != null) { definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory); explicitFactoryUsed = true; } if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) { if (explicitFactoryUsed) { logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionTemplate != null) { if (explicitFactoryUsed) { logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate); explicitFactoryUsed = true; } if (!explicitFactoryUsed) { if (logger.isDebugEnabled()) { logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); } definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); } } } return beanDefinitions; }
總結(jié):spring-mybatis與原生Mybatis相比,如下概念:
1)SqlSessionFactory類在兩者中都存在
2)前者用SqlSessionFactoryBean生成SqlSessionFactory,后者則使用SqlSessionFactoryBuilder;
3)前者使用SqlSessionTemplate,后者使用SqlSession,實際上前者實現(xiàn)了后者
4)MapperFactoryBean中實現(xiàn)了原生mybatis中下面的步驟,因此通過該類可以直接獲取到一個mapper接口的實現(xiàn)對象
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
總結(jié)
以上所述是小編給大家介紹的spring-mybatis與原生mybatis使用對比分析,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- Spring Boot整合MyBatis操作過程
- 基于SpringBoot與Mybatis實現(xiàn)SpringMVC Web項目
- 詳解Spring Boot整合Mybatis實現(xiàn) Druid多數(shù)據(jù)源配置
- Spring Boot 集成Mybatis實現(xiàn)主從(多數(shù)據(jù)源)分離方案示例
- springboot + mybatis配置多數(shù)據(jù)源示例
- Spring Boot MyBatis 連接數(shù)據(jù)庫配置示例
- SpringMvc+Mybatis+Pagehelper分頁詳解
- SpringMVC與Mybatis集合實現(xiàn)調(diào)用存儲過程、事務(wù)控制實例
相關(guān)文章
MyEclipse設(shè)置Console輸出到文件的實現(xiàn)方法
下面小編就為大家?guī)硪黄狹yEclipse設(shè)置Console輸出到文件的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
IDEA?Ui設(shè)計器JFormDesigner?永久激活插件+注冊機(親測一直在用)
這篇文章主要介紹了IDEA?Ui設(shè)計器JFormDesigner?永久激活----插件+注冊機?自己一直在用的版本和注冊機,非常不錯,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
Spring Boot項目如何同時支持HTTP和HTTPS協(xié)議的實現(xiàn)
這篇文章主要介紹了Spring Boot項目如何同時支持HTTP和HTTPS協(xié)議的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
openEuler?搭建java開發(fā)環(huán)境的詳細(xì)過程
這篇文章主要介紹了openEuler?搭建java開發(fā)環(huán)境,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06
Java String、StringBuffer與StringBuilder的區(qū)別
本文主要介紹Java String、StringBuffer與StringBuilder的區(qū)別的資料,這里整理了相關(guān)資料及詳細(xì)說明其作用和利弊點,有需要的小伙伴可以參考下2016-09-09

