spring-mybatis与原生mybatis使用对比

本文介绍了Spring框架下整合MyBatis的四种常见方法,包括使用MapperFactoryBean、SqlSessionTemplate、SqlSessionDaoSupport及MapperScannerConfigurer等组件。通过这些方法可以有效减少配置工作量并提高代码复用率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原生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, "name", "1", "123@qq.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的实现类org.mybatis.spring.SqlSessionTemplate

mybatis中, sessionFactory可由SqlSessionFactoryBuilder.来创建。MyBatis-Spring
中,使用了SqlSessionFactoryBean来替代。SqlSessionFactoryBean有一个必须属性dataSource,另外其还有一个通用属性configLocation(用来指定mybatis的xml配置文件路径)。SqlSessionFactoryBean即相当于原生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>
//使用方法:
@Repository
public 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 {
 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());
  }
  private class SqlSessionInterceptor implements InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      SqlSession sqlSession = getSqlSession(
          SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType,
          SqlSessionTemplate.this.exceptionTranslator);
      try {
        Object result = method.invoke(sqlSession, args);
        if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          // force commit even on non-dirty sessions because some databases require
          // a commit/rollback before calling close()
          sqlSession.commit(true);
        }
        return result;
      } catch (Throwable t) {
        Throwable unwrapped = unwrapThrowable(t);
        if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
          // release the connection to avoid a deadlock if the translator is no loaded. See issue #22
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
          sqlSession = null;
          Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
          if (translated != null) {
            unwrapped = translated;
          }
        }
        throw unwrapped;
      } finally {
        if (sqlSession != null) {
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
        }
      }
    }
  }

如上面代码所示,SqlSessionTemplate类实现了原生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>
package com.hdst.app;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;

import java.sql.Connection;
import java.util.List;
import java.util.Map;

/**
 * Created by lujie on 2018/9/12.
 */
public  class BaseDao extends SqlSessionDaoSupport {
    //使用sqlSessionFactory
    @Autowired   
    private SqlSessionFactory sqlSessionFactory;      
    @Autowired   
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory)    
    {        
        super.setSqlSessionFactory(sqlSessionFactory);    
    }    
    /**   
     * 执行insert操作   
     * @param statement   
     * @return   */  
    public int insert(String statement) {    
        return getSqlSession().insert(statement);  
    }  
    /**   
     * * 执行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);  
    }    

    /**   
     * * 根据参数 获取一个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, 以便执行较为复杂的用法   * @return   */  
    public Connection getConnection() {    
        return getSqlSession().getConnection();  
    }  
}

如上代码,一个Dao类继承了SqlSessionDaoSupport类后,就可以在类中注入SessionFactory,进而通过getSqlSession()获取当前SqlSession下面是SqlSessionDaoSupport的源码,它是一个抽象类,并拥有sqlSession属性,在setSqlSessionFactory方法中实例化了该sqlSession

package org.mybatis.spring.support;

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

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.dao.support.DaoSupport;

/**
 * Convenient super class for MyBatis SqlSession data access objects.
 * It gives you access to the template which can then be used to execute SQL methods.
 * <p>
 * This class needs a SqlSessionTemplate or a SqlSessionFactory.
 * If both are set the SqlSessionFactory will be ignored.
 * <p>
 * {code Autowired} was removed from setSqlSessionTemplate and setSqlSessionFactory
 * in version 1.2.0.
 * 
 * @author Putthibong Boonbong
 *
 * @see #setSqlSessionFactory
 * @see #setSqlSessionTemplate
 * @see SqlSessionTemplate
 * @version $Id$
 */
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;
  }

  /**
   * Users should use this method to get a SqlSession to call its statement methods
   * This is SqlSession is managed by spring. Users should not commit/rollback/close it
   * because it will be automatically done.
   *
   * @return Spring managed thread safe SqlSession
   */
  public SqlSession getSqlSession() {
    return this.sqlSession;
  }

  /**
   * {@inheritDoc}
   */
  protected void checkDaoConfig() {
    notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
  }

}
方法四:(也是最常见的使用方法,使用MapperScannerConfigurer,它将会查找类路径下的映射器并自动将它们创建成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这个类:

总结:spring-mybatis与原生Mybatis相比,
1)SqlSessionFactory类在两者中都存在
2)前者用SqlSessionFactoryBean生成SqlSessionFactory,后者则使用SqlSessionFactoryBuilder;
3)前者使用SqlSessionTemplate,后者使用SqlSession,实际上前者实现了后者
4)MapperFactoryBean中实现了原生mybatis中下面的步骤,因此通过该类可以直接获取到一个mapper接口的实现对象 ,MapperFactoryBean继承SqlSessionDaoSupport
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);

转自:https://juejin.im/post/5a0e9c6ff265da432528e0b0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值