知道mybatis的人一定都知道ibatis,虽然说现在ibatis都不怎么被使用了,但是这也不能够让我们放弃对于ibatis的了解,下面一起来看看ibatis的原理方面的内容吧!
ibatis是一个基于Java的半自动化的持久框架,下面来看一下ibatis的核心类图。
SqlMapClient类它是ibatis的门面,通过ibatis完成的持久化操作都是通过调用SqlMapClient类完成的。
SqlMapClient把所有的操作都转给类SqlMapExecutorDelegate类,SqlMapExecutorDelegate类存放解析配置文件生成的类。
例如:
数据源,parameterMap,resultMap, MappedStatement(对增删改查语句的封装)等等,SqlExecutor是最终执行sql语句的地方。
MappedStatement类包含对参数数组进行包装的ParameterMapping[]数组,对执行结果进行包装的ResultMapping[]数组。还有对各种不同的sql的包装类Sql。
例如:
一个插入语句,传进来的是一个对象,ibatis就会依据数的数组包装类ParameterMapping[]将参数赋值。
这里的话,这个赋值是通过DataExchange类完成的。
下面是具体的代码:
public Object[] getProperties(Object object) { int i = 0; Object[] values = new Object[propertyNames.length]; try { for (i = 0; i < propertyNames.length; i++) { try { values[i] = getters[i].invoke(object, NO_ARGUMENTS); } catch (Throwable t) { throw ClassInfo.unwrapThrowable(t); } } } catch (Throwable t) { throw new RuntimeException("Error getting property '" + getters[i].getName() + "' of '" + object + "'. Cause: " + t, t); } return values; }
对于一个查询语句,对执行结果的处理是通过对ResultMapping[]进行循环处理的,下面是核心代码:
for (int i = 0; i < getResultMappings() .length; i++) { ResultMapping mapping = (ResultMapping) getResultMappings()[i]; errorContext.setMoreInfo(mapping.getErrorString()); 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(statementScope, rs, mapping, javaType); } else if (DomTypeMarker.class.isAssignableFrom(resultClass)) { Class javaType = mapping.getJavaType(); if (javaType == null) { javaType = DomTypeMarker.class; } columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, javaType); } else { Probe p = ProbeFactory.getProbe(resultClass); Class type = p.getPropertyTypeForSetter(resultClass, mapping.getPropertyName()); columnValues[i] = getNestedSelectMappingValue(statementScope, 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; } } }
在这当中,typetype为参数的java类型,Probe p = ProbeFactory.getProbe(resultClass),Class type = p.getPropertyTypeForSetter(resultClass, mapping.getPropertyName())是通过反射获取java类型的getNestedSelectMappingValue(statementScope, rs, mapping, type)调用了prepareBeanParameterObject(StatementScope statementScope, ResultSet rs, ResultMapping mapping, Class parameterType)方法。
下面是具体的方法:
private Object prepareBeanParameterObject(StatementScope statementScope, ResultSet rs, ResultMapping mapping, Class parameterType)
代码:
throws InstantiationException, IllegalAccessException, SQLException { TypeHandlerFactory typeHandlerFactory = getDelegate() .getTypeHandlerFactory(); Object parameterObject; if (parameterType == null) { parameterObject = new HashMap(); } else { parameterObject = ResultObjectFactoryUtil.createObjectThroughFactory(parameterType); } String complexName = mapping.getColumnName(); if (complexName.indexOf('=') > -1 || complexName.indexOf(',') > -1) { StringTokenizer parser = new StringTokenizer(complexName, "{}=, ", false); while (parser.hasMoreTokens()) { String propName = parser.nextToken(); String colName = parser.nextToken(); Class propType = PROBE.getPropertyTypeForSetter(parameterObject, propName); TypeHandler propTypeHandler = typeHandlerFactory.getTypeHandler(propType); Object propValue = propTypeHandler.getResult(rs, colName); PROBE.setObject(parameterObject, propName, propValue); } } else { // single param TypeHandler propTypeHandler = typeHandlerFactory.getTypeHandler(parameterType); if (propTypeHandler == null) { propTypeHandler = typeHandlerFactory.getUnkownTypeHandler(); } parameterObject = propTypeHandler.getResult(rs, complexName); } return parameterObject;
typeHandlerFactory依据参数parameterType的类型决定采用哪个handler处理ResultSet的结果,以
StringTypeHandler为例,其getResult(ResultSet rs, String columnName)方法:
public Object getResult(ResultSet rs, String columnName) throws SQLException { Object s = rs.getString(columnName); if (rs.wasNull()) { return null; } else { return s; } }
对于ibatis原理你都了解了吗?你对于ibatis框架还有什么不理解的地方吗?请继续通过java架构师栏目来进行相关知识的了解个学习吧。
推荐阅读: