上一篇:html
http://www.javashuo.com/article/p-qiqbpoee-bc.htmlsql
分析了MapperMethod從建立到執行的過程,MapperMethod的執行包括執行sql返回結果.mybatis
在執行sql和返回結果的過程當中就會涉及到參數類型的轉換,這個過程是經過TypeHandler來處理的.關於TypeHandler官網有比較詳細的文檔http://www.mybatis.org/mybatis-3/zh/configuration.html#typeHandlers,文檔主要說明了如何使用TypeHandler,在下面的分析中將重點分析與TypeHandler有關的源碼.app
MyBatis有默認的類型處理器,若是須要自定義配置也至關簡單,在mybatis-config.xml裏添加以下配置:ide
<typeHandlers> <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/> </typeHandlers>
下面分析配置讀取設置的過程,在XMLConfigBuilder中源碼分析
/** * 讀取配置文件組裝configuration * @param root 配置文件的configuration節點 */ private void parseConfiguration(XNode root) { try { //issue #117 read properties first propertiesElement(root.evalNode("properties")); Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectorFactoryElement(root.evalNode("reflectorFactory")); settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
在以上源碼中有一行ui
typeHandlerElement(root.evalNode("typeHandlers"));
再來看typeHandlerElement這個方法spa
/** * 讀取typeHandlers配置並註冊 * @param parent 配置文件typeHandlers節點 * @throws Exception */ private void typeHandlerElement(XNode parent) throws Exception { if (parent != null) { for (XNode child : parent.getChildren()) { if ("package".equals(child.getName())) { String typeHandlerPackage = child.getStringAttribute("name"); typeHandlerRegistry.register(typeHandlerPackage); } else { String javaTypeName = child.getStringAttribute("javaType"); String jdbcTypeName = child.getStringAttribute("jdbcType"); String handlerTypeName = child.getStringAttribute("handler"); Class<?> javaTypeClass = resolveClass(javaTypeName); JdbcType jdbcType = resolveJdbcType(jdbcTypeName); Class<?> typeHandlerClass = resolveClass(handlerTypeName); if (javaTypeClass != null) { if (jdbcType == null) { typeHandlerRegistry.register(javaTypeClass, typeHandlerClass); } else { typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass); } } else { typeHandlerRegistry.register(typeHandlerClass); } } } } }
if和else中的代碼邏輯對應了typeHandler的兩種配置方式.最後都會調用 .net
typeHandlerRegistry.register()
以上是TypeHandler與TypeHandlerRegistry,Configuration,BaseTypeHandler之間的關係.
設置參數時先調用ParameterHandler.setParameters(),而後在setParameters()裏獲取相應的typeHandler,最後調用typeHandler.setParameter()
再來看看BaseTypeHandler的setParameter方法
當parameter不爲null時調用的是setNonNullParameter,也就是說子類須要實現setNonNullParameter
BigIntegerTypeHandler的源碼:
public void setNonNullParameter(PreparedStatement ps, int i, BigInteger parameter, JdbcType jdbcType) throws SQLException { ps.setBigDecimal(i, new BigDecimal(parameter)); }
至此,TypeHandler的做用已經大體分析完畢了.