- 浏览: 169563 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
Jindev:
多线程批量检测未注册域名 -
仰望摩天轮:
用webloginc或者websphere容器的时候 jps抄 ...
BTrace使用总结 -
duoniK:
赞,忍不住转载分享一下
BTrace使用总结 -
aliensb:
api callback error!是怎么回事,谢谢
多线程批量检测未注册域名 -
springdata-jpa:
java struts框架demo使用实例教程源代码下载,地址 ...
struts1源码分析(一)整体概览和核心组件
在ibatis整体设计和核心流程一文中,我们提到了ibatis框架中sql的执行过程,sql执行前后有两个重要步骤: 参数对象映射到sql执行参数,sql执行结果映射到结果对象。本文将深入分析ibatis框架中参数和结果的映射原理。
问题
在详细介绍ibatis参数和结果映射原理之前,让我们先来思考几个问题。
1. 为什么需要参数和结果的映射?
相对于全自动的orm,ibatis一个重要目标是,通过维护POJO与SQL之间的映射关系,让我们执行 SQL时对输入输出的数据管理更加方便。也就是说,ibatis并不会为程序员在运行期自动生成SQL 执行,具体的 SQL 需要程序员编写,然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定POJO。
2. 如何维护参数和结果的映射关系?
对于变化的数据,当然是通过配置文件的方式,在sqlMap映射文件中配置参数和结果对象与SQL的映射关系。
3. 如何执行参数和结果与SQL的映射?
初始化时读取配置文件,将参数和结果与SQL的映射关系维护在SqlMapClientImpl中;处理请求时,通过配置的映射关系,构建sql参数和结果对象,可以采用反射等方式读取和写入对象的属性值。
SQL执行环境
在ibatis整体设计和核心流程一文的SQL执行过程中,SqlMapExecutorDelegate首先获取初始化时构建好的MappedStatement (初始化过程见初始化和配置文件解析),再通过MappedStatement执行SQL,参数和结果与SQL的映射正是在MappedStatement的SQL执行过程中进行处理。在介绍参数和结果与SQL的映射原理之前,我们先看一下MappedStatement的相关类图:
上面的这张类图需说明两点:
1. 从纵向上体现了Statement类的整体继承关系,MappedStatement接口提供了SQL执行上下文信息和执行操作,如ParameterMap、ResultMap、SQL、Timeout等上下文信息和executeQueryForList等操作信息;BaseStatement抽象类提供了MappedStatement的初步实现,它组合了MappedStatement需要的上下文信息;GeneralStatement实现类提供了MappedStatement的执行操作的基本实现;InsertStatement、SelectStatement等实现类提供了针对不同类型SQL操作的特定实现。
2. 从横向上体现了Statement类的初始化数据和请求处理数据的分离。 类图中的第一行对象(ParameterMap/ResultMap/SQL等)在初始化过程中会构造完毕,请求处理时直接获取即可; 类图中的第三行对象(RequestScope)在请求处理时才会创建,通过执行方法的参数传入,再进行后续处理。
映射主要类图
参数和结果映射的主要类图如下:
1. ParameterMap
该接口提供了和参数处理相关的方法,如根据参数对象生成sql参数数组,为PrepareStatement设置参数等。它的默认实现类是BasicParameterMap,其内部组合了多个ParameterMapping对象。
2. ResultMap
该接口提供了和结果处理相关的方法,如根据ResultSet生成结果对象等。它的默认实现类是BasicResultMap,其内部组合了多个ResultMapping对象。
3. ParameterMapping/ResultMapping
该接口用于维护参数对象和结果对象中每个属性的详细映射信息,如propertyName、jdbcType、javaType、nullValue等,以及针对该属性类型的TypeHandler。
4. DataExchange
该接口是映射的核心接口,执行具体的映射操作,默认实现是BaseDataExchange,针对不同的参数和结果类型有不同的实现类,如JavaBeanDataExchange、MapDataExchange、ListDataExchange、PrimitiveDataExchange等,这些对象统一由DataExchangeFactory创建和管理。
下面以查询操作为例,分析ibatis执行过程中参数和结果的映射原理。
参数映射过程
1. SqlMapExecutorDelegate调用GeneralStatement.executeQueryWithCallback()方法,执行sql语句。
该方法执行过程中,有非常重要的两步: 根据参数对象生成sql执行参数数组,该步在parameterMap.getParameterObjectValues()中完成;通过参数数组为PrepareStatement设置参数,该步在sqlExecuteQuery()方法中完成。下面重点看一下这两个的方法的实现。
2. BasicParameterMap.getParameterObjectValues()的实现如下:
可以看出,参数对象映射主要交给dataExchange对象完成,针对不同的parameterClass,BasicParameterMap初始化时会创建不同的dataExchange对象。这里以MapDataExchange对象为例,说明参数的映射过程。
3. MapDataExchange.getData()的实现如下:
可以看出,map参数对象的映射方式是,通过循环处理每一个ParameterMapping对象获得属性名称,再从map参数中获取对应的属性值,最终放入参数数组中。有兴趣的同学可以看一下JavaBeanDataExchange的实现,其内部通过组合AccessPlan对象,使用反射方式生成参数数组。
4. 通过上面两步已经获得了sql执行参数数组,sqlExecuteQuery()方法将通过参数数组为PrepareStatement设置参数。sqlExecuteQuery()方法内部调用SqlExecutor.executeQuery()进行查询,部分源码如下:
上面方法中通过调用getParameterMap().setParameters(request, ps, parameters)为PrepareStatement设置参数,其中BasicParameterMap().setParameters()源码如下:
在前面参数数组生成时我们看到,parameterMappings和参数数组是一一对应关系,并且保证前后顺序,这里再循环处理每一个parameterMappings和相应参数值,为PrepareStatement设置参数。 其中setParameter()方法如下:
上面的方法最终调用TypeHandler进行参数设置,下面以BigDecimalTypeHandler为例,看一下setParameter()方法实现:
到这里,谜底已经揭开了。
总结一下上面整个过程: 初始化时通过配置文件构建ParameterMap;请求处理时再通过ParameterMap构建出对应的sql参数数组,这个构建过程通过调用dataExchange对象完成;最后通过sql参数数组为PrepareStatement设置参数。
结果映射过程
1. 在参数映射过程的第4步中,最后一行代码是handleMultipleResults(),正是这里进行结果映射,部分源码如下:
2. handleResults()方法的实现如下:
上面方法中依次处理ResultSet的每条记录,首先获取该记录的属性值数组,该步通过BasicResultMap.getResults()方法实现;再将属性值数组装换成结果对象,该步通过RowHandlerCallback.handleResultObject()方法实现;最后存储在RowHandlerCallback对象中,最终结果在GeneralStatement中通过rowHandler.getList()返回。下面分别看一下这两个方法的具体实现。
3. BasicResultMap.getResults()的部分源码如下:
上面的代码依次处理ResultMappings,设置每个属性值,最后统一放入columnValues数组中。
4. RowHandlerCallback.handleResultObject()方法的实现如下:
该方法内部实现调用BasicResultMap.setResultObjectValues()生成结果对象,再将结果对象保存在RowHandler中。setResultObjectValues()方法目标是将属性值设置到对象中,部分场景是借助上文提及的dataExchange对象实现,这里就不再详述。
小结
最后,以一张图总结参数和结果的映射整体流程:
每个映射过程都主要拆分为两步,为什么需要这样的设计?一个核心的原因是实现职责分离,不同阶段借助不同的处理方式(dataExchange,typeHandler等),使整个处理逻辑更清晰。
问题
在详细介绍ibatis参数和结果映射原理之前,让我们先来思考几个问题。
1. 为什么需要参数和结果的映射?
相对于全自动的orm,ibatis一个重要目标是,通过维护POJO与SQL之间的映射关系,让我们执行 SQL时对输入输出的数据管理更加方便。也就是说,ibatis并不会为程序员在运行期自动生成SQL 执行,具体的 SQL 需要程序员编写,然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定POJO。
2. 如何维护参数和结果的映射关系?
对于变化的数据,当然是通过配置文件的方式,在sqlMap映射文件中配置参数和结果对象与SQL的映射关系。
3. 如何执行参数和结果与SQL的映射?
初始化时读取配置文件,将参数和结果与SQL的映射关系维护在SqlMapClientImpl中;处理请求时,通过配置的映射关系,构建sql参数和结果对象,可以采用反射等方式读取和写入对象的属性值。
SQL执行环境
在ibatis整体设计和核心流程一文的SQL执行过程中,SqlMapExecutorDelegate首先获取初始化时构建好的MappedStatement (初始化过程见初始化和配置文件解析),再通过MappedStatement执行SQL,参数和结果与SQL的映射正是在MappedStatement的SQL执行过程中进行处理。在介绍参数和结果与SQL的映射原理之前,我们先看一下MappedStatement的相关类图:
上面的这张类图需说明两点:
1. 从纵向上体现了Statement类的整体继承关系,MappedStatement接口提供了SQL执行上下文信息和执行操作,如ParameterMap、ResultMap、SQL、Timeout等上下文信息和executeQueryForList等操作信息;BaseStatement抽象类提供了MappedStatement的初步实现,它组合了MappedStatement需要的上下文信息;GeneralStatement实现类提供了MappedStatement的执行操作的基本实现;InsertStatement、SelectStatement等实现类提供了针对不同类型SQL操作的特定实现。
2. 从横向上体现了Statement类的初始化数据和请求处理数据的分离。 类图中的第一行对象(ParameterMap/ResultMap/SQL等)在初始化过程中会构造完毕,请求处理时直接获取即可; 类图中的第三行对象(RequestScope)在请求处理时才会创建,通过执行方法的参数传入,再进行后续处理。
映射主要类图
参数和结果映射的主要类图如下:
1. ParameterMap
该接口提供了和参数处理相关的方法,如根据参数对象生成sql参数数组,为PrepareStatement设置参数等。它的默认实现类是BasicParameterMap,其内部组合了多个ParameterMapping对象。
2. ResultMap
该接口提供了和结果处理相关的方法,如根据ResultSet生成结果对象等。它的默认实现类是BasicResultMap,其内部组合了多个ResultMapping对象。
3. ParameterMapping/ResultMapping
该接口用于维护参数对象和结果对象中每个属性的详细映射信息,如propertyName、jdbcType、javaType、nullValue等,以及针对该属性类型的TypeHandler。
4. DataExchange
该接口是映射的核心接口,执行具体的映射操作,默认实现是BaseDataExchange,针对不同的参数和结果类型有不同的实现类,如JavaBeanDataExchange、MapDataExchange、ListDataExchange、PrimitiveDataExchange等,这些对象统一由DataExchangeFactory创建和管理。
下面以查询操作为例,分析ibatis执行过程中参数和结果的映射原理。
参数映射过程
1. SqlMapExecutorDelegate调用GeneralStatement.executeQueryWithCallback()方法,执行sql语句。
protected void executeQueryWithCallback(RequestScope request, Connection conn, Object parameterObject, Object resultObject, RowHandler rowHandler, int skipResults, int maxResults) throws SQLException { ... parameterObject = validateParameter(parameterObject); //校验输入参数 Sql sql = getSql(); //获取sql对象 errorContext.setMoreInfo("Check the parameter map."); ParameterMap parameterMap = sql.getParameterMap(request, parameterObject); //从sql对象中获取ParameterMap errorContext.setMoreInfo("Check the result map."); ResultMap resultMap = sql.getResultMap(request, parameterObject); //从sql对象中获取ResultMap request.setResultMap(resultMap); request.setParameterMap(parameterMap); Object[] parameters = parameterMap.getParameterObjectValues(request, parameterObject); //重要,目的是通过参数映射获取参数值 errorContext.setMoreInfo("Check the SQL statement."); String sqlString = sql.getSql(request, parameterObject); //获取sql语句 errorContext.setActivity("executing mapped statement"); errorContext.setMoreInfo("Check the SQL statement or the result map."); RowHandlerCallback callback = new RowHandlerCallback(resultMap, resultObject, rowHandler); sqlExecuteQuery(request, conn, sqlString, parameters, skipResults, maxResults, callback); // 重要,执行sql操作 ... }
该方法执行过程中,有非常重要的两步: 根据参数对象生成sql执行参数数组,该步在parameterMap.getParameterObjectValues()中完成;通过参数数组为PrepareStatement设置参数,该步在sqlExecuteQuery()方法中完成。下面重点看一下这两个的方法的实现。
2. BasicParameterMap.getParameterObjectValues()的实现如下:
public Object[] getParameterObjectValues(RequestScope request, Object parameterObject) { return dataExchange.getData(request, this, parameterObject); }
可以看出,参数对象映射主要交给dataExchange对象完成,针对不同的parameterClass,BasicParameterMap初始化时会创建不同的dataExchange对象。这里以MapDataExchange对象为例,说明参数的映射过程。
3. MapDataExchange.getData()的实现如下:
public Object[] getData(RequestScope request, ParameterMap parameterMap, Object parameterObject) { if (!(parameterObject instanceof Map)) { throw new RuntimeException("Error. Object passed into MapDataExchange was not an instance of Map."); } Object[] data = new Object[parameterMap.getParameterMappings().length]; Map map = (Map) parameterObject; ParameterMapping[] mappings = parameterMap.getParameterMappings(); for (int i = 0; i < mappings.length; i++) { data[i] = map.get(mappings[i].getPropertyName()); } return data; }
可以看出,map参数对象的映射方式是,通过循环处理每一个ParameterMapping对象获得属性名称,再从map参数中获取对应的属性值,最终放入参数数组中。有兴趣的同学可以看一下JavaBeanDataExchange的实现,其内部通过组合AccessPlan对象,使用反射方式生成参数数组。
4. 通过上面两步已经获得了sql执行参数数组,sqlExecuteQuery()方法将通过参数数组为PrepareStatement设置参数。sqlExecuteQuery()方法内部调用SqlExecutor.executeQuery()进行查询,部分源码如下:
public void executeQuery(RequestScope request, Connection conn, String sql, Object[] parameters, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException { ... PreparedStatement ps = null; ResultSet rs = null; setupResultObjectFactory(request); try { errorContext.setMoreInfo("Check the SQL Statement (preparation failed)."); Integer rsType = request.getStatement().getResultSetType(); //准备PrepareStatement if (rsType != null) { ps = prepareStatement(request.getSession(), conn, sql, rsType); } else { ps = prepareStatement(request.getSession(), conn, sql); } setStatementTimeout(request.getStatement(), ps); Integer fetchSize = request.getStatement().getFetchSize(); if (fetchSize != null) { ps.setFetchSize(fetchSize.intValue()); } errorContext.setMoreInfo("Check the parameters (set parameters failed)."); request.getParameterMap().setParameters(request, ps, parameters); //为PrepareStatement设置参数 errorContext.setMoreInfo("Check the statement (query failed)."); ps.execute(); //执行 errorContext.setMoreInfo("Check the results (failed to retrieve results)."); // Begin ResultSet Handling rs = handleMultipleResults(ps, request, skipResults, maxResults, callback); //处理结果 ... }
上面方法中通过调用getParameterMap().setParameters(request, ps, parameters)为PrepareStatement设置参数,其中BasicParameterMap().setParameters()源码如下:
public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters) throws SQLException { .... if (parameterMappings != null) { for (int i = 0; i < parameterMappings.length; i++) { BasicParameterMapping mapping = (BasicParameterMapping) parameterMappings[i]; errorContext.setMoreInfo(mapping.getErrorString()); if (mapping.isInputAllowed()) { setParameter(ps, mapping, parameters, i); //循环处理每一个参数 } } } }
在前面参数数组生成时我们看到,parameterMappings和参数数组是一一对应关系,并且保证前后顺序,这里再循环处理每一个parameterMappings和相应参数值,为PrepareStatement设置参数。 其中setParameter()方法如下:
protected void setParameter(PreparedStatement ps, BasicParameterMapping mapping, Object[] parameters, int i) throws SQLException { Object value = parameters[i]; // 设置空值 String nullValueString = mapping.getNullValue(); if (nullValueString != null) { TypeHandler handler = mapping.getTypeHandler(); if (handler.equals(value, nullValueString)) { value = null; } } // 设置Parameter TypeHandler typeHandler = mapping.getTypeHandler(); if (value != null) { typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName()); } else if (typeHandler instanceof CustomTypeHandler) { typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName()); } else { int jdbcType = mapping.getJdbcType(); if (jdbcType != JdbcTypeRegistry.UNKNOWN_TYPE) { ps.setNull(i + 1, jdbcType); } else { ps.setNull(i + 1, Types.OTHER); } } }
上面的方法最终调用TypeHandler进行参数设置,下面以BigDecimalTypeHandler为例,看一下setParameter()方法实现:
public void setParameter(PreparedStatement ps, int i, Object parameter, String jdbcType) throws SQLException { ps.setBigDecimal(i, ((BigDecimal) parameter)); }
到这里,谜底已经揭开了。
总结一下上面整个过程: 初始化时通过配置文件构建ParameterMap;请求处理时再通过ParameterMap构建出对应的sql参数数组,这个构建过程通过调用dataExchange对象完成;最后通过sql参数数组为PrepareStatement设置参数。
结果映射过程
1. 在参数映射过程的第4步中,最后一行代码是handleMultipleResults(),正是这里进行结果映射,部分源码如下:
private ResultSet handleMultipleResults(PreparedStatement ps, RequestScope request, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException { ResultSet rs; rs = getFirstResultSet(ps); if (rs != null) { handleResults(request, rs, skipResults, maxResults, callback); } ... }
2. handleResults()方法的实现如下:
private void handleResults(RequestScope request, ResultSet rs, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException { try { request.setResultSet(rs); ResultMap resultMap = request.getResultMap(); ... int resultsFetched = 0; while ((maxResults == SqlExecutor.NO_MAXIMUM_RESULTS || resultsFetched < maxResults) && rs.next()) { Object[] columnValues = resultMap.resolveSubMap(request, rs).getResults(request, rs); //获取每条记录的各个属性值 callback.handleResultObject(request, columnValues, rs); //通过属性值组装结果对象 resultsFetched++; } } } finally { request.setResultSet(null); } }
上面方法中依次处理ResultSet的每条记录,首先获取该记录的属性值数组,该步通过BasicResultMap.getResults()方法实现;再将属性值数组装换成结果对象,该步通过RowHandlerCallback.handleResultObject()方法实现;最后存储在RowHandlerCallback对象中,最终结果在GeneralStatement中通过rowHandler.getList()返回。下面分别看一下这两个方法的具体实现。
3. BasicResultMap.getResults()的部分源码如下:
public Object[] getResults(RequestScope request, ResultSet rs) throws SQLException { ... boolean foundData = false; Object[] columnValues = new Object[getResultMappings().length]; // 依次处理ResultMappings,设置每个属性值 for (int i = 0; i < getResultMappings().length; i++) { BasicResultMapping mapping = (BasicResultMapping) getResultMappings()[i]; if (mapping.getStatementName() != null) { if (resultClass == null) { throw new SqlMapException("The result class was null when trying to get results for ResultMap named " + getId() + "."); } else if (Map.class.isAssignableFrom(resultClass)) { Class javaType = mapping.getJavaType(); if (javaType == null) { javaType = Object.class; } columnValues[i] = getNestedSelectMappingValue(request, rs, mapping, javaType); } else if (DomTypeMarker.class.isAssignableFrom(resultClass)) { Class javaType = mapping.getJavaType(); if (javaType == null) { javaType = DomTypeMarker.class; } columnValues[i] = getNestedSelectMappingValue(request, rs, mapping, javaType); } else { Probe p = ProbeFactory.getProbe(resultClass); Class type = p.getPropertyTypeForSetter(resultClass, mapping.getPropertyName()); columnValues[i] = getNestedSelectMappingValue(request, rs, mapping, type); } foundData = foundData || columnValues[i] != null; } else if (mapping.getNestedResultMapName() == null) { columnValues[i] = getPrimitiveResultMappingValue(rs, mapping); if (columnValues[i] == null) { columnValues[i] = doNullMapping(columnValues[i], mapping); } else { foundData = true; } } } request.setRowDataFound(foundData); return columnValues; }
上面的代码依次处理ResultMappings,设置每个属性值,最后统一放入columnValues数组中。
4. RowHandlerCallback.handleResultObject()方法的实现如下:
public void handleResultObject(RequestScope request, Object[] results, ResultSet rs) throws SQLException { Object object; request.setCurrentNestedKey(null); object = resultMap.resolveSubMap(request, rs).setResultObjectValues(request, resultObject, results); //生成结果对象 ... rowHandler.handleRow(object); // 将object加入rowHandler内部的list中 } }
该方法内部实现调用BasicResultMap.setResultObjectValues()生成结果对象,再将结果对象保存在RowHandler中。setResultObjectValues()方法目标是将属性值设置到对象中,部分场景是借助上文提及的dataExchange对象实现,这里就不再详述。
小结
最后,以一张图总结参数和结果的映射整体流程:
每个映射过程都主要拆分为两步,为什么需要这样的设计?一个核心的原因是实现职责分离,不同阶段借助不同的处理方式(dataExchange,typeHandler等),使整个处理逻辑更清晰。
发表评论
-
ibatis源码学习(五)缓存设计和实现
2012-04-07 21:06 4794缓存不算是ibatis框架的一个亮点,但理解i ... -
ibatis源码学习(五)缓存设计和实现
2012-04-07 09:30 0缓存不算是ibatis框架的一个亮点,但理解i ... -
ibatis源码学习(四)动态SQL的实现原理
2012-04-03 16:47 7259动态SQL是ibatis框架的一个重要特性,本 ... -
ibatis源码学习(二)初始化和配置文件解析
2012-03-11 00:15 6039在ibatis整体设计和核心 ... -
ibatis源码学习(一)整体设计和核心流程
2012-03-09 08:48 7390本文主要从ibatis框架的基本代码骨架进行切入,理解ibat ...
相关推荐
描述中的"ibatis框架源码剖析书中附带的光盘,ibatis源码分析"暗示这可能是一个学习资源,用于深入理解iBATIS的工作原理,可能包括了对源码的详细解读和分析。 **iBATIS核心知识点** 1. **SQL映射**:iBATIS的核心...
通过深入分析iBATIS的源码,开发者不仅可以了解其工作原理,还能学习到设计模式、数据库访问的最佳实践以及如何优雅地处理数据库操作。对于提升Java开发者的技能和理解数据库访问层的实现有极大的帮助。在实际开发中...
1. SQL Map配置文件:Ibatis的核心是SQL Map配置文件,其中包含了SQL语句和参数映射的定义。通过XML或者注解方式,开发者可以声明存储过程、动态SQL等,使得SQL与业务代码解耦。 2. 映射器(Mapper)接口:映射器...
总的来说,ibatis框架源码的学习不仅可以帮助我们理解其工作原理,提升开发效率,还能为我们提供一种思考问题的角度,理解数据访问层的设计模式。通过对源码的深入剖析,我们可以更好地解决实际项目中的问题,进行...
深入研究iBatis源码有助于理解其内部工作原理,包括如何解析XML配置文件,如何执行SQL语句,以及如何进行结果映射。源码分析可以帮助开发者更好地定制和优化自己的应用。 六、iBatis实践项目 通过实践项目,可以...
这个“iBatis源码jar包以后上传”可能指的是将要分享或者提供iBatis的源码jar包,以便于开发者深入学习和理解其内部工作原理。 首先,让我们来了解一下iBatis的基本概念和工作流程。iBatis的核心是SQL Map配置文件...
此外,你会学习到iBATIS的参数映射和结果映射机制。参数映射将Java对象的属性与SQL语句中的参数对应起来,使得可以方便地传递参数。结果映射则负责将数据库查询的结果转换为Java对象,通过`<resultMap>`标签定义了...
1. SQL映射文件:这是XML格式的文件,用于定义SQL语句和结果映射。通过这些文件,开发者可以声明式地编写SQL,使得SQL与业务逻辑分离,易于维护。 2. DAO(Data Access Object):是iBATIS中的一个设计模式,用于...
2. **参数映射**:学习如何通过paramterType和resultType属性进行参数和结果的类型声明。 3. **动态元素**:如if、choose、when、otherwise等,它们在XML映射文件中用于构建动态SQL。 三、**帮助文档** IBatis的...
通过学习和分析这个源码,开发者不仅可以深入了解SpringMVC和iBatis的协同工作原理,还可以掌握如何在Eclipse这样的IDE中配置和运行这样的项目。这有助于提升对MVC模式的理解,提高数据库操作的能力,以及熟练运用...
2. **MappedStatement**:每个SQL语句在iBATIS中都对应一个MappedStatement对象,包含了SQL语句、参数映射和结果映射。 3. **Executor**:执行器是iBATIS的核心组件,负责处理SQL的执行,包括简单执行、批量执行和...
5. `Mapper XML`文件:定义SQL语句和结果映射,与Mapper接口一一对应。 四、IbatisDemo运行流程 1. 加载配置:程序启动时,Ibatis会加载SqlMapConfig.xml,从中获取数据源和Mapper配置信息。 2. 创建...
5. **参数映射和结果映射**:通过`<parameterMap>`和`<resultMap>`标签,可以定义复杂参数和结果对象的映射。 6. **缓存机制**:Ibatis提供了一级缓存和二级缓存,可以优化查询性能,减少对数据库的访问。 7. **...
2. Mappings:映射文件是XML格式的,其中包含了SQL查询、参数映射和结果集映射。映射文件允许灵活地配置参数,支持动态SQL,比如根据条件选择性地执行某个部分。 3. SQL Session:SQL Session是iBATIS与数据库进行...
4. **参数映射与结果映射**:通过`@Param`和`@ResultMap`注解,你可以指定参数类型和结果集的映射,实现Java对象与数据库表字段的自动对应。 5. **Executor执行器**:Ibatis的Executor是执行SQL的接口,有...
iBatis通过解析XML映射文件来获取SQL语句和参数映射信息。映射文件包含以下关键元素: - `<mapper>`:定义一个Mapper接口,映射到特定的XML文件。 - `<select>`、`<insert>`、`<update>`、`<delete>`:分别对应SQL...
此外,Mybatis的Executor执行器负责处理SQL的执行,而ParameterHandler、ResultSetHandler和StatementHandler三个处理器则分别处理参数设置、结果集解析和SQL语句的创建。 对于DB2数据库的支持,Ibatis和Mybatis都...
XML映射中,SQL语句、参数和结果集映射都在XML文件中定义;注解映射则将这些信息直接写在Mapper接口的方法上,更简洁但可能不便于维护。 五、Ibatis的动态SQL 动态SQL是Ibatis的一大亮点,它允许在XML映射文件中...
5. 参数映射:在调用存储过程或自定义SQL时,iBATIS通过ParameterMap处理参数绑定,源码会展示如何映射输入参数和处理输出参数。 6. 简化的DAO层:iBATIS使得开发者可以专注于业务逻辑,而不必编写大量重复的JDBC...
在本资料中,我们将深入学习iBATIS的基本概念、配置、映射文件以及如何通过源码实践来理解其工作原理。 首先,让我们了解一下iBATIS的核心功能。iBATIS的核心是SQL Maps,它是一种XML格式的文件,用于定义数据库...