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, "name", "1", "[email protected]"); 
           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>        
            
    <property name="mapperLocations" value="classpath:mapper/*.xml">property>    
bean>


<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

    
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">        
    <property name="dataSource" ref="dataSource" />        
    <property name="configLocation"  value="classpath:sqlMapConfig.xml"/>        
            
    <property name="mapperLocations" value="classpath:com/hua/saf/**/*.xml" />    
bean>        

    
<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


    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation"  value="classpath:sqlMapConfig.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.
 * 

* This class needs a SqlSessionTemplate or a SqlSessionFactory. * If both are set the SqlSessionFactory will be ignored. *

* {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


    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        
        <property name="mapperLocations" value="classpath:com/hua/saf/**/*.xml" />
    bean>

    
    <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

你可能感兴趣的:(MyBatis)