ibatis是什么?ibatis是一个基于Java的"半自动化"的持久框架,"半自动化"是指ibatis并不会在运行期自动生成sql语句执行,而是具体的sql需要通过配置文件进行编写,并将所需的参数,以及返回的结果字段映射到指定的POJO.
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;
- }
其中object是传进来的要插入的对象,propertyNames就是ParameterMapping[]的参数数组,getters是object类的所有get方法的Method方法数组
对于一个查询语句,对执行结果的处理,是通过对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;
- }
- }
- }
其中,type为参数的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;
- }
- }