ibatis的技术是从xml里面字符串转换成JAVA对象,对象填充JDBC的statement查询,然后从resultset取对象返回,另外利用ThreadLocal实现线程安全,JDBC保证了事务控制,cache(三方库)实现缓存的dao框架。

各大包结构和作用:

1,accessplan—

2,builder.xml

3,cache

4,datasource

5,exchange—ResultMap(sql结果类型结构)和ParameterMap(sql条件类型结果)与值的相互转换

6,execution

7,impl

8,mapping

9,scop

10,transaction

11,type—jdbc的Statement和ResultSet 与 java.lang.Object对象的相互转换。

Accessplan

uml:

Accessplan对外只提供个Factory,这种“封闭”设计可以借鉴:

对外接口调用如下:

  1. parameterPlan = AccessPlanFactory.getAccessPlan(parameterMap.getParameterClass(), parameterPropNames);

其中parameterMap.getParameterClass(),是映射的CLASS,就是XML里parameterXXX里的类,后面那个是类的成员变量,ParameterMapping是映射元素类,如下:

// 从某个映射对象中取出所有元素

ParameterMapping[] parameterMappings = parameterMap.getParameterMappings();

String[] parameterPropNames = new String[parameterMappings.length];
        for (int i = 0; i < parameterPropNames.length; i++) {

// 从元素中取出被映射对象的成员名
          parameterPropNames[i] = parameterMappings[i].getPropertyName();
        }

UML:

ResultGetter和ParameterSetter的设计看来是为了TypeHandlerCallback扩展的复杂数据类型所用。为什么需要在这中间加一层呢? 可能是因为数据的复杂性吧,把特例和一般分离出来,代码看上去似乎优雅些。继续深入。

元数据接口

TypeHandler接口的抽象意义——Interface for getting data into, and out of a mapped statement,主要的作用是把Object那些对象set到jdbc的statement,以及从resultset结果集中获取那些Object对象。

  1. /**
  2. * Interface for getting data into, and out of a mapped statement
  3. */
  4. publicinterface TypeHandler {
  5. // para向第i个位置填充ps.
  6. public void setParameter(PreparedStatement ps,int i, Object parameter, String jdbcType)
  7. throws SQLException;
  8. // 根据rs结果集某字段名取值
  9. public Object getResult(ResultSet rs, String columnName)
  10. throws SQLException;
  11. public Object getResult(ResultSet rs, int columnIndex)
  12. throws SQLException;
  13. /**
  14. * Converts the String to the type that this handler deals with
  15. */
  16. public Object valueOf(String s);
  17. public boolean equals(Object object, String string);
  18. }

TypeHandlerCallback接口抽象意义为:

A simple interface for implementing custom type handlers.
Using this interface, you can implement a type handler that
will perform customized processing before parameters are set
on a PreparedStatement and after values are retrieved from
a ResultSet.

  1. publicinterface TypeHandlerCallback {
  2. public void setParameter(ParameterSetter setter, Object parameter)// 同上
  3. throws SQLException;
  4. public Object getResult(ResultGetter getter) // 同上
  5. throws SQLException;
  6. public Object valueOf(String s);
  7. }

StringTypeHandler——String类型帮助类

  1. publicclass StringTypeHandlerextends BaseTypeHandlerimplements TypeHandler {
  2. public void setParameter(PreparedStatement ps,int i, Object parameter, String jdbcType)
  3. throws SQLException {
  4. ps.setString(i, ((String) parameter));
  5. }
  6. public Object getResult(ResultSet rs, String columnName)
  7. throws SQLException {
  8. Object s = rs.getString(columnName); // 很熟悉的jdbc编程吧
  9. if (rs.wasNull()) {
  10. return null;
  11. } else {
  12. return s;
  13. }
  14. }
  15. public Object getResult(ResultSet rs, int columnIndex)
  16. throws SQLException {
  17. Object s = rs.getString(columnIndex);
  18. if (rs.wasNull()) {
  19. return null;
  20. } else {
  21. return s;
  22. }
  23. }
  24. }

最后“元数据”这块剩下最后一个Factory管理类:TypeHandlerFactory

  1. /**
  2. * Not much of a suprise, this is a factory class for TypeHandler objects.
  3. */
  4. publicclass TypeHandlerFactory {
  5. private final Map typeHandlerMap =new HashMap();// 用final Map来存储类型转换的帮助类
  6. private final TypeHandler unknownTypeHandler =new UnknownTypeHandler(this);
  7. private final HashMap typeAliases =new HashMap();// 保存type助记符,为什么呢?
  8. /**
  9. * Default constructor
  10. */
  11. public TypeHandlerFactory() {
  12. TypeHandler handler;
  13. handler = new BooleanTypeHandler();
  14. register(Boolean.class, handler);// 实际上把handler放入布尔值的map,然后再放入typeMap里。
  15. register(boolean.class, handler);
  16. handler = new ByteTypeHandler();
  17. register(Byte.class, handler);
  18. register(byte.class, handler);
  19. register(String.class,new StringTypeHandler());
  20. register(String.class,"CLOB", new CustomTypeHandler(newClobTypeHandlerCallback()));
  21. register(String.class,"LONGVARCHAR", new CustomTypeHandler(newClobTypeHandlerCallback()));
  22. register(byte[].class,new ByteArrayTypeHandler());
  23. register(byte[].class,"BLOB", new CustomTypeHandler(newBlobTypeHandlerCallback()));
  24. register(byte[].class,"LONGVARBINARY", new CustomTypeHandler(newBlobTypeHandlerCallback()));
  25. ....
  26. putTypeAlias("string", String.class.getName());
  27. putTypeAlias("byte", Byte.class.getName());
  28. putTypeAlias("long", Long.class.getName());
  29. ....
  30. }
  31. /* Public Methods */
  32. public TypeHandler getTypeHandler(Class type, String jdbcType) {
  33. Map jdbcHandlerMap = (Map) typeHandlerMap.get(type);
  34. TypeHandler handler = null;
  35. if (jdbcHandlerMap != null) {
  36. handler = (TypeHandler) jdbcHandlerMap.get(jdbcType);
  37. if (handler == null) {
  38. handler = (TypeHandler) jdbcHandlerMap.get(null);
  39. }
  40. }
  41. return handler;
  42. }
  43. /**
  44. * When in doubt, get the "unknown" type handler
  45. *
  46. * @return - if I told you, it would not be unknown, would it?
  47. */
  48. public TypeHandler getUnkownTypeHandler() {
  49. return unknownTypeHandler;
  50. }
  51. /**
  52. * Tells you if a particular class has a TypeHandler
  53. *
  54. * @param type - the class
  55. *
  56. * @return - true if there is a TypeHandler
  57. */
  58. public boolean hasTypeHandler(Class type) {
  59. return getTypeHandler(type) != null;
  60. }
  61. /**
  62. * Register (add) a type handler for a class and JDBC type
  63. *
  64. * @param type - the class
  65. * @param jdbcType - the JDBC type
  66. * @param handler - the handler instance
  67. */
  68. public void register(Class type, String jdbcType, TypeHandler handler) {
  69. Map map = (Map) typeHandlerMap.get(type);
  70. if (map == null) {
  71. map = new HashMap();
  72. typeHandlerMap.put(type, map);
  73. }
  74. map.put(jdbcType, handler);
  75. }
  76. /**
  77. * Lookup an aliased class and return it's REAL name
  78. *
  79. * @param string - the alias
  80. *
  81. * @return - the REAL name
  82. */
  83. public String resolveAlias(String string) {
  84. String key = null;
  85. if(string != null)
  86. key = string.toLowerCase();
  87. String value = null;
  88. if (typeAliases.containsKey(key)) {
  89. value = (String) typeAliases.get(key);
  90. } else {
  91. value = string;
  92. }
  93. return value;
  94. }
  95. /**
  96. * Adds a type alias that is case insensitive.  All of the following String, string, StRiNg will equate to the same alias.
  97. * @param alias - the alias
  98. * @param value - the real class name
  99. */
  100. public void putTypeAlias(String alias, String value) {
  101. String key = null;
  102. if(alias != null)
  103. key = alias.toLowerCase();
  104. if (typeAliases.containsKey(key) && !typeAliases.get(key).equals(value)) {
  105. throw new SqlMapException("Error in XmlSqlMapClientBuilder.  Alias name conflict occurred.  The alias '" + key +"' is already mapped to the value '" + typeAliases.get(alias) +"'.");
  106. }
  107. typeAliases.put(key, value);
  108. }
  109. }

Mapping包

--parameter包意义——主要负责数据类型转换,把xml写的字符串映射成正确的类型,以上type包是解决了object到type的转换。

UML:

ParameterMap接口

  1. publicinterface ParameterMap {
  2. public String getId();
  3. public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters)
  4. throws SQLException;
  5. public Object[] getParameterObjectValues(RequestScope request, Object parameterObject);
  6. public CacheKey getCacheKey(RequestScope request, Object parameterObject);
  7. public void refreshParameterObjectValues(RequestScope request, Object parameterObject, Object[] values);
  8. public ParameterMapping[] getParameterMappings();
  9. public Class getParameterClass();
  10. }

ParameterMapping接口

  1. publicinterface ParameterMapping {
  2. public String getPropertyName();
  3. public boolean isOutputAllowed();
  4. }

BasicParameterMapping实现类:

  1. publicclass BasicParameterMappingimplements ParameterMapping {
  2. private staticfinal String MODE_INOUT ="INOUT";
  3. private staticfinal String MODE_OUT ="OUT";
  4. private staticfinal String MODE_IN ="IN";
  5. private String propertyName; // 从XML文件里读取需要转换的类型名
  6. private TypeHandler typeHandler; // 对象转换相应类型的工具map
  7. private String typeName; // this is used for REF types or user-defined types
  8. private int jdbcType;
  9. private String jdbcTypeName;
  10. private String nullValue;
  11. private String mode;
  12. private boolean inputAllowed;
  13. private boolean outputAllowed;
  14. private Class javaType; // 需要转换的类型class
  15. private String resultMapName; // 结果map名称
  16. private Integer numericScale;
  17. private String errorString;
  18. public BasicParameterMapping() {
  19. mode = "IN";
  20. inputAllowed = true;
  21. outputAllowed = false;
  22. }
  23. public void setJavaTypeName(String javaTypeName) {
  24. try {
  25. if (javaTypeName == null) {
  26. this.javaType = null;
  27. } else {// 通过getClassLoader().loadClass(className);来获得实例
  28. this.javaType = Resources.classForName(javaTypeName);
  29. }
  30. } catch (ClassNotFoundException e) {
  31. throw new SqlMapException("Error setting javaType property of ParameterMap.  Cause: " + e, e);
  32. }
  33. }
  34. }

BasicParameterMap实现类

    1. publicclass BasicParameterMapimplements ParameterMap {
    2. private String id;
    3. private Class parameterClass;
    4. private ParameterMapping[] parameterMappings;
    5. private DataExchange dataExchange;
    6. private String resource;
    7. private Map parameterMappingIndex = new HashMap();
    8. private SqlMapExecutorDelegate delegate;
    9. public void setParameterMappingList(List parameterMappingList) {
    10. this.parameterMappings = (BasicParameterMapping[]) parameterMappingList.toArray(newBasicParameterMapping[parameterMappingList.size()]);
    11. for (int i =0; i < parameterMappings.length; i++) {
    12. parameterMappingIndex.put(parameterMappings[i].getPropertyName(),new Integer(i));
    13. }
    14. Map props = new HashMap();
    15. props.put("map",this);
    16. dataExchange = delegate.getDataExchangeFactory().getDataExchangeForClass(parameterClass);
    17. dataExchange.initialize(props);
    18. }
    19. /**
    20. * @param ps
    21. * @param parameters
    22. * @throws java.sql.SQLException
    23. */
    24. public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters)
    25. throws SQLException {
    26. ErrorContext errorContext = request.getErrorContext();
    27. errorContext.setActivity("applying a parameter map");
    28. errorContext.setObjectId(this.getId());
    29. errorContext.setResource(this.getResource());
    30. errorContext.setMoreInfo("Check the parameter map.");
    31. if (parameterMappings != null) {
    32. for (int i =0; i < parameterMappings.length; i++) {
    33. BasicParameterMapping mapping = (BasicParameterMapping) parameterMappings[i];
    34. errorContext.setMoreInfo(mapping.getErrorString());
    35. if (mapping.isInputAllowed()) {
    36. setParameter(ps, mapping, parameters, i);
    37. }
    38. }
    39. }
    40. }
    41. public Object[] getParameterObjectValues(RequestScope request, Object parameterObject) {
    42. return dataExchange.getData(request, this, parameterObject);
    43. }
    44. public CacheKey getCacheKey(RequestScope request, Object parameterObject) {
    45. return dataExchange.getCacheKey(request, this, parameterObject);
    46. }
    47. public void refreshParameterObjectValues(RequestScope request, Object parameterObject, Object[] values) {
    48. dataExchange.setData(request, this, parameterObject, values);
    49. }
    50. protected void setParameter(PreparedStatement ps, BasicParameterMapping mapping, Object[] parameters,int i) throws SQLException {
    51. Object value = parameters[i];
    52. // Apply Null Value
    53. String nullValueString = mapping.getNullValue();
    54. if (nullValueString != null) {
    55. TypeHandler handler = mapping.getTypeHandler();
    56. if (handler.equals(value, nullValueString)) {
    57. value = null;
    58. }
    59. }
    60. // Set Parameter
    61. TypeHandler typeHandler = mapping.getTypeHandler();
    62. if (value != null) {
    63. typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());
    64. } else if (typeHandlerinstanceof CustomTypeHandler) {
    65. typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());
    66. } else {
    67. int jdbcType = mapping.getJdbcType();
    68. if (jdbcType != JdbcTypeRegistry.UNKNOWN_TYPE) {
    69. ps.setNull(i + 1, jdbcType);
    70. } else {
    71. ps.setNull(i + 1, Types.OTHER);
    72. }
    73. }
    74. }
    75. }

ibatis源码学习3_源码包结构的更多相关文章

  1. 【 js 基础 】【 源码学习 】源码设计 (持续更新)

    学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析第二部分:undersc ...

  2. 【 js 基础 】【 源码学习 】源码设计 (更新了backbone分析)

    学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析 第二部分:unders ...

  3. jquery源码学习(一)——jquery结构概述以及如何合适的暴露全局变量

    jQuery 源码学习是对js的能力提升很有帮助的一个方法,废话不说,我们来开始学习啦 我们学习的源码是jquery-2.0.3已经不支持IE6,7,8了,因为可以少学很多hack和兼容的方法. jq ...

  4. USB2.0协议学习笔记---USB数据包结构

    USB包类型和传输过程  USB是一种串行总线,因此数据都是一位一位传输的,如同串口那样,但是USB在真实物理电路上却不是TTL电平,而是一种差分信号采用NRZI编码,就是用变化表示0,不变表示1,同 ...

  5. Vue2.x源码学习笔记-源码目录结构整理

    先从github上下载或者clone一个vue分支项目 https://github.com/vuejs/vue 查看下目录结果 先列出一些目录 Vue |— build 打包相关的配置文件,其中最重 ...

  6. springFramework 源码学习之源码下载与编译

    1.源码下载 Spring已经将源码从svn迁移到了git.对于习惯了svn的人来说依然可以svn checkout,最好checkout到英文路径下,本人中文路径编译不过,具体原因不明,路径: ht ...

  7. VUE 源码学习01 源码入口

    VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...

  8. vue 源码学习(一) 目录结构和构建过程简介

    Flow vue框架使用了Flow作为类型检查,来保证项目的可读性和维护性.vue.js的主目录下有Flow的配置.flowconfig文件,还有flow目录,指定了各种自定义类型. 在学习源码前可以 ...

  9. async源码学习 - 全部源码

    因为工作需要,可能我离前端走远了,偏node方向了.所以异步编程的需求很多,于是乎,不得不带着学习async了. 我有个习惯,用别人的东西之前,喜欢稍微搞明白点,so就带着看看其源码. github: ...

随机推荐

  1. python开发_python中的list操作

    对python中list的操作,大家可以参考: Python list 操作 以下是我个人的笔记: ============================================ Add b ...

  2. [转] C#2010 在TreeView控件下显示路径下所有文件和文件夹

    原文 张丹-小桥流水,C#2010 在TreeView控件下显示路径下所有文件和文件夹 C#2010学习过程中有所收获,便总结下来,希望能给和我一样在学习遇到困难的同学提供参考. 本文主要介绍两个自定 ...

  3. 用django实现redirect的几种方法总结

    用django开发web应用, 经常会遇到从一个旧的url转向一个新的url.这种隐射也许有规则,也许没有.但都是为了实现业务的需要.总体说来,有如下几种方法实现 django的 redirect.1 ...

  4. Spring Boot实践——Filter实现

    Filter介绍 Filter是Servlet规范规定的,不属于spring框架,也是用于请求的拦截.但是它适合更粗粒度的拦截,在请求前后做一些编解码处理.日志记录等. 一个Filter包括:1).在 ...

  5. Sass 入门 (一) 安装Sass

    Sass安装 ruby安装 因为sass依赖于ruby环境,所以装sass之前先确认装了ruby.先导官网下载个ruby 在安装的时候,请勾选Add Ruby executables to your ...

  6. springMVC环境搭建(1)

    工作一年以来,写的都是.net,最近比较闲,想把之前学过的java相关的东西捡起来,也学点新的东西.以前做过SSH架构,一直好奇spring mvc是怎么样的,所以今天试试看. 总体的代码结构 手动输 ...

  7. aop中的顾问

    通知只能指定织入的时间点,目标方法之前,之后,环绕,还是异常时. 要想指定切入点就要使用顾问

  8. aop中通知详情

  9. 深度学习篇——Tensorflow配置(傻瓜安装模式)

    前言 如果你是一个完美主义者,那么请绕过此文,请参考<深度学习篇——Tensorflow配置(完美主义模式)> 安装 pip install tensorflow ok,只要不报错,安装就 ...

  10. 第五章 大数据平台与技术 第12讲 大数据处理平台Spark

    Spark支持多种的编程语言 对比scala和Java编程上节课的计数程序.相比之下,scala简洁明了. Hadoop的IO开销大导致了延迟高,也就是说任务和任务之间涉及到I/O操作.前一个任务完成 ...