`
18211103738
  • 浏览: 83033 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

MyBatis查询的源码分析

 
阅读更多

如下为mybatis的一个集合查询: 

String resource = "mybatis.cfg.xml";  
Reader reader = Resources.getResourceAsReader(resource);  
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);  
	
SqlSession sqlSession = ssf.openSession();  
	
try {  
	List<User> users = sqlSession.selectList("User.selectUser", "1");  //查询状态为1的用户
	for (User user : users) {
		System.out.println(user);  
	}
} catch (Exception e) {  
	e.printStackTrace();  
} finally {  
	sqlSession.close();
}

  

  • 其中SqlSession默认为DefaultSqlSession:
public class DefaultSqlSession implements SqlSession {

  private Configuration configuration;
  private Executor executor;
... ...

  @Override
  public <E> List<E> selectList(String statement) {
    return this.selectList(statement, null);
  }

  @Override
  public <E> List<E> selectList(String statement, Object parameter) {
    return this.selectList(statement, parameter, RowBounds.DEFAULT);	//其中RowBounds.DEFAULT为new RowBounds();
  }

  @Override
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
	//MappedStatement是mybatis根据<select id="selectByExample" resultMap="ResultMap" ... />创建的映射对象
      MappedStatement ms = configuration.getMappedStatement(statement);
      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

... ...
}
/**
  * 行数限制
  */
public class RowBounds {

  public static final int NO_ROW_OFFSET = 0;
  public static final int NO_ROW_LIMIT = Integer.MAX_VALUE;
  public static final RowBounds DEFAULT = new RowBounds();

  private int offset;
  private int limit;

  public RowBounds() {
    this.offset = NO_ROW_OFFSET;
    this.limit = NO_ROW_LIMIT;
  }

  public RowBounds(int offset, int limit) {
    this.offset = offset;
    this.limit = limit;
  }
... ...
}

  

  • 当我们启用缓存后查询执行器Executor为CachingExector:
public class CachingExecutor implements Executor {

  private Executor delegate;
  private TransactionalCacheManager tcm = new TransactionalCacheManager();

  public CachingExecutor(Executor delegate) {
    this.delegate = delegate;//这里的delegate为abstract class BaseExecutor implements Executor
    delegate.setExecutorWrapper(this);
  }
... ...

  @Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameterObject);
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

  @Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
    Cache cache = ms.getCache();
    if (cache != null) {
      flushCacheIfRequired(ms);//如果<select id="selectByExample" resultMap="ResultMap" flushCache="true" ... />中设置flushCache="true",则清除缓存
      if (ms.isUseCache() && resultHandler == null) {
        ensureNoOutParams(ms, parameterObject, boundSql);//确保查询不包括输出参数,因为缓存程序不支持输出参数
        @SuppressWarnings("unchecked")
        List<E> list = (List<E>) tcm.getObject(cache, key);//从缓存管理器中获取缓存(缓存管理器是对各区块缓存的统一管理工具)
        if (list == null) {	//如果从缓存中获取不到,则执行查询
          list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
          tcm.putObject(cache, key, list); //将查询到的结果放入缓存
        }
        return list;
      }
    }
    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

... ...

}

 

  • CachingExecutor中的执行器代理delegate一般为ReuseExecutor:
public class ReuseExecutor extends BaseExecutor {

... ...

  @Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Configuration configuration = ms.getConfiguration();
    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
    Statement stmt = prepareStatement(handler, ms.getStatementLog());
    return handler.<E>query(stmt, resultHandler); //执行查询
  }

... ...

}

 

  • StatementHandler一般为路由StatementHandler,即RoutingStatementHandler:
public class RoutingStatementHandler implements StatementHandler {

  private final StatementHandler delegate;

  public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
/*这里的switch-case即是传说中的策略模式*/
    switch (ms.getStatementType()) {
      case STATEMENT:
        delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case PREPARED:
        delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case CALLABLE:
        delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      default:
        throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
    }

  }

 

  • RoutingStatementHandler其中的StatementHandler代理delegate,通常为PreparedStatementHandler;其中的query(...)方法通过调用ResultHandler的handleResultSets(...)封装查询结果:
public class PreparedStatementHandler extends BaseStatementHandler {

... ...
  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();	//执行查询
    return resultSetHandler.<E> handleResultSets(ps);	//处理结果集
  }
... ...
}

 

  • ResultSetHandler只有一个默认结果集处理器DefaultResultSetHandler:
public interface ResultSetHandler {
  /**
    * 处理结果集
    */
  <E> List<E> handleResultSets(Statement stmt) throws SQLException;

... ...

}
public class DefaultResultSetHandler implements ResultSetHandler {
  ... ...
  // nested resultmaps
  private final Map<CacheKey, Object> nestedResultObjects = new HashMap<CacheKey, Object>();//嵌套结果缓存
  private final Map<CacheKey, Object> ancestorObjects = new HashMap<CacheKey, Object>();//祖对象缓存,即最外层的对象缓存
  private final Map<String, String> ancestorColumnPrefix = new HashMap<String, String>();
  ... ...
  
  /**
    * 处理所有的结果集(一次查询可能有多个语句,所以可能有多个结果集)
    */
  @Override
  public List<Object> handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

    final List<Object> multipleResults = new ArrayList<Object>();

    int resultSetCount = 0;
    ResultSetWrapper rsw = getFirstResultSet(stmt);//获取java.sql.ResultSet的第一个结果集(此时sql已被执行)

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {	//遍历所有的结果集(一般仅一个结果集,因为通常仅一条查询语句)
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);	//根据ResultSetWrapper和ResultMap处理结果集
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }

/*---------该方法中的以下代码暂且不做分析------------*/
    String[] resultSets = mappedStatement.getResulSets();
    if (resultSets != null) {
      while (rsw != null && resultSetCount < resultSets.length) {
        ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
        if (parentMapping != null) {
          String nestedResultMapId = parentMapping.getNestedResultMapId();
          ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
          handleResultSet(rsw, resultMap, null, parentMapping);
        }
        rsw = getNextResultSet(stmt);
        cleanUpAfterHandlingResultSet();
        resultSetCount++;
      }
    }

    return collapseSingleResultList(multipleResults);
  }

... ...

  private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
    try {
      if (parentMapping != null) {
        handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
      } else {
        if (resultHandler == null) {//使用结果处理器为空,则生成一个默认结果处理器
          DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
          handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);	//处理记录集
          multipleResults.add(defaultResultHandler.getResultList());
        } else {
          handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);			//处理记录集
        }
      }
    } finally {
      // issue #228 (close resultsets)
      closeResultSet(rsw.getResultSet());
    }
  }

... ...

  /**
* 处理所有行记录中的值
*/
  private void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
    if (resultMap.hasNestedResultMaps()) {
      ensureNoRowBounds();
      checkResultHandler();
      handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);//嵌套映射
    } else {
      handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);//简单映射
    }
  }

... ...

  /**
    * 处理行值集到简单结果的映射
    */
  private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
      throws SQLException {
    DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
    skipRows(rsw.getResultSet(), rowBounds);
    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
      Object rowValue = getRowValue(rsw, discriminatedResultMap);
      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
    }
  }

... ...

   /**
    * 处理行值集到嵌套结果的映射
    */
   private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
    final DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
    skipRows(rsw.getResultSet(), rowBounds);
    Object rowValue = null;
    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
      final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
      final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);
      Object partialObject = nestedResultObjects.get(rowKey);//尝试从nestedResultObjects(是HashMap<CacheKey, Object>)中获取原对象
      if (mappedStatement.isResultOrdered()) {
        if (partialObject == null && rowValue != null) {
          nestedResultObjects.clear();
          storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
        }
        rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject);//获取行值
      } else {
        rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject);//获取行值
        if (partialObject == null) {
          storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
        }
      }
    }
    if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {
      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
    }
  }

... ...


  /**
    * 创建缓存的KEY(具体key的生成策略可详见文末)
    */
  private CacheKey createRowKey(ResultMap resultMap, ResultSetWrapper rsw, String columnPrefix) throws SQLException {
    final CacheKey cacheKey = new CacheKey();
    cacheKey.update(resultMap.getId());
    List<ResultMapping> resultMappings = getResultMappingsForRowKey(resultMap);
    if (resultMappings.size() == 0) {
      if (Map.class.isAssignableFrom(resultMap.getType())) {
        createRowKeyForMap(rsw, cacheKey);
      } else {
        createRowKeyForUnmappedProperties(resultMap, rsw, cacheKey, columnPrefix);
      }
    } else {
      createRowKeyForMappedProperties(resultMap, rsw, cacheKey, resultMappings, columnPrefix);
    }
    return cacheKey;
  }

... ...

  /**
    * 从查询的一条行记录中获取需要映射为结果属性的值
    */
  private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, CacheKey absoluteKey, String columnPrefix, Object partialObject) throws SQLException {
    final String resultMapId = resultMap.getId();
    Object resultObject = partialObject;
/*如果传过来的原对象不为空,则向其中设置属性值;
否则,创建一个新结果对象作为原对象,然后设置属性值*/
    if (resultObject != null) {
      final MetaObject metaObject = configuration.newMetaObject(resultObject);
      putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix);
      applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false);	//应用嵌套映射
      ancestorObjects.remove(absoluteKey);
    } else {
      final ResultLoaderMap lazyLoader = new ResultLoaderMap();
      resultObject = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
      if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
        final MetaObject metaObject = configuration.newMetaObject(resultObject);
        boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();
        if (shouldApplyAutomaticMappings(resultMap, true)) {
          foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
        }
	   //属性映射
        foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
        putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix);
	   //嵌套映射
        foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues;
        ancestorObjects.remove(absoluteKey);
        foundValues = lazyLoader.size() > 0 || foundValues;
        resultObject = foundValues ? resultObject : null;
      }
      if (combinedKey != CacheKey.NULL_CACHE_KEY) {
        nestedResultObjects.put(combinedKey, resultObject);
      }
    }
    return resultObject;
  }

... ...

  /**
    * 应用属性映射
    */
  private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)
      throws SQLException {
    final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
    boolean foundValues = false;
    final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
    for (ResultMapping propertyMapping : propertyMappings) {
      String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
      if (propertyMapping.getNestedResultMapId() != null) {
        // the user added a column attribute to a nested result map, ignore it
        column = null;
      }
      if (propertyMapping.isCompositeResult()
          || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))
          || propertyMapping.getResultSet() != null) {
        Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
        final String property = propertyMapping.getProperty();
        if (value != DEFERED
            && property != null
            && (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive()))) {
          metaObject.setValue(property, value);
        }
        if (value != null || value == DEFERED) {
          foundValues = true;
        }
      }
    }
    return foundValues;
  }

... ...

   /**
    * 应用嵌套结果映射
    */
   private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) {
    boolean foundValues = false;
//循环结果映射中所有的属性映射,如果属性为对象,即嵌套结果映射,则递归调用getRowValue(...)方法
    for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {
      final String nestedResultMapId = resultMapping.getNestedResultMapId();
      if (nestedResultMapId != null && resultMapping.getResultSet() == null) {
        try {
          final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping);
          final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix);
          CacheKey rowKey = null;
          Object ancestorObject = null;
          if (ancestorColumnPrefix.containsKey(nestedResultMapId)) {
            rowKey = createRowKey(nestedResultMap, rsw, ancestorColumnPrefix.get(nestedResultMapId));
            ancestorObject = ancestorObjects.get(rowKey);
          }
          if (ancestorObject != null) {
            if (newObject) {
              linkObjects(metaObject, resultMapping, ancestorObject); // issue #385
            }
          } else {
            rowKey = createRowKey(nestedResultMap, rsw, columnPrefix);
            final CacheKey combinedKey = combineKeys(rowKey, parentRowKey);
            Object rowValue = nestedResultObjects.get(combinedKey);
            boolean knownValue = (rowValue != null);
            instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // mandatory            
            if (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw.getResultSet())) {
		   //递归调用getRowValue(...)方法
              rowValue = getRowValue(rsw, nestedResultMap, combinedKey, rowKey, columnPrefix, rowValue);
              if (rowValue != null && !knownValue) {
                linkObjects(metaObject, resultMapping, rowValue);
                foundValues = true;
              }
            }
          }
        } catch (SQLException e) {
          throw new ExecutorException("Error getting nested result map values for '" + resultMapping.getProperty() + "'.  Cause: " + e, e);
        }
      }
    }
    return foundValues;
  }
}
/**
  * 结果映射
  */
public class ResultMap {
  private String id;		//结果映射ID
  private Class<?> type;	//映射结果类型
  private List<ResultMapping> resultMappings;	//所有内嵌的结果映射
  private List<ResultMapping> idResultMappings;	//所有内嵌的ID结果映射
  private List<ResultMapping> constructorResultMappings;	//所有构造映射
  private List<ResultMapping> propertyResultMappings;		//所有的属性映射
... ...

  private ResultMap() {
  }
... ...
}

 

  • 备注:DefaultResultSetHandler中CacheKey的创建策略
<resultMap id="BaseResultMap" type="com.muwu.mjh.product.model.Cupboard" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="name" property="name" jdbcType="VARCHAR" />
    <result column="mark" property="mark" jdbcType="VARCHAR" />
<association property="unit" javaType="com.muwu.mjh.system.model.Unit" autoMapping="false">
    	<id property="id" column="unit_id"/>
    	<result property="name" column="unit_name"/>
    </association>
	<association property="productType" javaType="com.muwu.mjh.product.model.ProductType" autoMapping="false">
    	<id property="id" column="product_type_id"/>
    	<result property="name" column="product_type_name"/>
    	<result property="parentId" column="parent_id"/>
    </association>
    <collection property="modules" ofType="com.muwu.mjh.product.model.cupboard.Module" autoMapping="false" >
    	<id property="id" column="module_id"/>
    	<id property="sort" column="module_sort"/>
    	<result property="name" column="module_name"/>
    	<result property="mark" column="module_mark"/>
    	<collection property="components" ofType="com.muwu.mjh.product.model.cupboard.Component" autoMapping="false">
    		<id property="id" column="component_id"/>
    		<result property="name" column="component_name"/>
    		<result property="mark" column="component_mark"/>
    		<result property="image" column="component_image"/>
    		<result property="picture" column="component_picture"/>
    	</collection>
    </collection>
</resultMap>

 

映射时生成的缓存key依次形如:

 

13544163:-1571759273:com.muwu.mjh.product.mapper.CupboardMapper.

    RichResultMap:id:16942

 

-2046111186:1023173599:com.muwu.mjh.product.mapper.CupboardMapper.

    mapper_resultMap[RichResultMap]_association[unit]:unit_id:10

 

2024729156:2397089841:com.muwu.mjh.product.mapper.CupboardMapper.

    mapper_resultMap[RichResultMap]_association[productType]:product_type_id:19

 

1199939766:-5622484385:com.muwu.mjh.product.mapper.CupboardMapper.

    mapper_resultMap[RichResultMap]_collection[modules]:module_id:51:module_sort:0

 

559266669:-1005085733:com.muwu.mjh.product.mapper.CupboardMapper.

    mapper_resultMap[RichResultMap]_collection[modules]_collection[components]:component_id:200

 

可见被<id property="..." column="..."/>标注的属性和字段值都会作为CacheKey的一部分

  • 大小: 22.2 KB
  • 大小: 20.6 KB
  • 大小: 15.8 KB
  • 大小: 13.1 KB
分享到:
评论

相关推荐

    MyBatis源码分析.pdf

    MyBatis源码分析 MyBatis是一款流行的Java持久层框架,提供了强大的数据库访问能力,本文将对MyBatis的源码进行深入分析,从而帮助读者更好地理解MyBatis的工作机理。 1. MyBatis入门 MyBatis是一款基于Java的...

    mybatis源码分析视频

    本资源“mybatis源码分析视频”是针对MyBatis框架进行深入剖析的教程,通过视频和文档的形式帮助学习者理解其内部工作机制。 1. **MyBatis简介** MyBatis消除了几乎所有的JDBC代码和手动设置参数以及获取结果集。...

    Mybatis源码分析.pdf

    总结起来,MyBatis源码分析涵盖了从配置加载到数据库操作的全过程,涉及到了配置解析、SQL执行、结果映射等多个关键环节,以及Executor、StatementHandler等核心组件。通过深入学习MyBatis的源码,开发者不仅可以...

    Java架构师之源码分析专题SpringBoot2.x、Spring5、SpringMVC、Mybatis源码分析

    最后,Mybatis作为持久层框架,它的源码分析主要集中在SQL映射文件的解析,动态SQL的生成,以及与数据库的交互。你将了解到Executor执行器的执行策略,StatementHandler如何处理SQL语句,以及ResultHandler如何处理...

    mybatis源码分析思维导图.rar

    MyBatis是一款流行的Java...总的来说,MyBatis源码分析思维导图会涵盖MyBatis的各个关键组件、工作流程、特性以及扩展机制。通过深入学习和理解这些内容,开发者能够更好地利用MyBatis进行数据库操作,并优化其性能。

    mybatis3.x源码深度解析与最佳实践.pdf

    本系列源码解析的方式将从 MyBatis 的源码入手,深入分析 MyBatis 的设计思路和实现机制。 2. 容器的加载与初始化 2.1 config 文件解析 XMLConfigBuilder.parseConfiguration 方法是 MyBatis 中的核心方法之一,...

    springBoot结合Mybatis的使用,其中包括了Mybaits的xml配置使用、Mybatis部分源码分析等内容

    SpringBoot结合Mybatis的使用Demo,项目中通过SpringBoot配置Mybaits,配置mybatis的xml文件,以及程序启动类上通过...并且对Mybatis部分源码分析记录到文件中。 通过本项目demo可以学会很多,希望资源对大家有用处!

    mybatis基础源码及jar包

    - 分析MyBatis的源码,了解其内部实现机制,如如何解析XML配置文件,如何生成动态代理等。 - 学习如何配置MyBatis环境,包括设置数据源、创建SqlSessionFactory等。 - 熟悉Mapper接口和XML映射文件的编写,理解SQL与...

    mybatis源码分析

    通过对MyBatis源码的分析,开发者可以更深入地理解其内部运作机制,从而更好地优化应用,解决实际问题。同时,这也是一种提升个人技术水平和解决问题能力的有效途径。在阅读源码过程中,可能会遇到各种设计模式和...

    Mybatis源码详细分析

    国内数据库访问层从之前火爆的Hibernate到现在绝大部分公司都用Mybatis,倒也不是说Mybatis比Hibernate优秀,看看现在Spring Data JPA底层的支持还是...下面就从项目的搭建到源码分析一步一步深入了解Mybatis。

    Mybatis 框架源码10种设计模式分析.pdf

    Mybatis 框架源码 10 种设计模式分析 Mybatis 框架源码 10 种设计模式分析是小傅哥博客的一篇文章,旨在分享 Mybatis 框架源码中的设计模式应用。文章首先提醒读者,学习设计模式和框架源码的重要性,不仅仅是为了...

    mybatis3 源码

    源码分析有助于理解MyBatis如何根据结果集和结果映射配置创建目标对象。 8. **TypeHandler** TypeHandler是MyBatis中处理Java类型和JDBC类型之间转换的关键组件。通过自定义TypeHandler,我们可以实现对特殊类型的...

    mybatis-3.2.2-src.rar 源码

    源码分析可以从以下几个主要方面展开: 1. **架构设计**:Mybatis 的核心组件包括SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession和Executor等。SqlSessionFactoryBuilder用于创建SqlSessionFactory,它...

    mybatis 的高级关联查询源码

    这次我们将深入探讨 MyBatis 如何实现这种高级关联查询,并通过源码分析来理解其工作原理。 “一对多”关联通常指的是一个实体(如用户)可以拥有多个关联实体(如订单)。在 MyBatis 中,我们可以使用 `...

    MyBatis源码分析中文PDF完整版最新版本

    此外,为了方便读者深入理解,本文还附带了一份MyBatis源码分析的PDF文档供参考。 文章结构如下: 1. 第一章:MyBatis基础入门 2. 第二章:配置文件的解析机制 3. 第三章:映射文件的解析流程 4. 第四章:SQL执行...

    mybatis-3.4.1源码

    通过对MyBatis 3.4.1源码的阅读和分析,开发者可以掌握MyBatis的内部工作流程,了解如何编写更高效、更灵活的数据访问代码。同时,对于想要深入持久层框架开发或者定制MyBatis功能的人来说,源码学习是必不可少的。

    mybatis实战源码

    - MyBatis提供了一个强大的插件机制,用户可以自定义拦截器实现SQL执行前后的增强功能,如日志、性能分析等。 7. MyBatis的Spring整合 - MyBatis与Spring整合后,可以使用Spring的事务管理,简化了事务控制和依赖...

    源码分析专题之Mybatis课程一之源码分析与实现.pdf

    根据提供的文件内容,我们可以展开关于Mybatis源码分析的详细知识点介绍。Mybatis是一个流行的Java持久层框架,它用于简化与数据库交互的复杂性。源码分析是理解框架内部工作原理的绝佳方式,同时也能够加深对设计...

    mybatis-plus源码

    在深入探讨MyBatis-Plus源码之前,我们先了解一下MyBatis-Plus的基本概念和作用。 MyBatis-Plus是对MyBatis框架的一种增强,它在MyBatis的基础上进行了功能扩展,比如自动填充字段、条件构造器、一键生成代码等,极...

Global site tag (gtag.js) - Google Analytics