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. 【nose入门】环境搭建

    http://blog.sina.com.cn/s/blog_65a8ab5d0101fihb.html 主要分为四个模块 一 环境搭建 二 demo测试 三 参数说明 四 注意事项 一  环境搭建 ...

  2. DNS_PROBE_FINISHED_NXDOMAIN

    DNS_PROBE_FINISHED_NXDOMAIN 用如下链接清除dns即可 chrome://net-internals/#dns dns不稳定 手动绑定host即可

  3. python学习——练习题(13)

    """ 题目:打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身.例如:153是一个" ...

  4. 页面生成柱状图 --- D3.js

    转载自:https://www.cnblogs.com/fastmover/p/7779660.html D3.js从入门到"放弃"指南 前言 近期略有点诸事不顺,趁略有闲余之时, ...

  5. how to use jquery with primefaces

    PrimeFaces already ships with jQuery bundled, yet you've downloaded and installed another one which ...

  6. VB导入Excel到数据库软件(持续更新中。)

    1.选择Excel文件版本 电脑上用的 Office2010 引用:Mircosoft Excel 14.0 Object Library 2.选择Excel文件 '选择文件公共变量 Public D ...

  7. Python常用的一些内建函数和math模块函数

    一:Python内建函数 # abs取绝对值 num = -10 print(abs(num)) # max 求最大值 print(max(6, 9, 2, 12, 8)) # min求最小值 pri ...

  8. sql 添加索引强大

    以前没有亲自添加过索引,今天添加了一下,果真强大.几百倍的速度提升. SELECT * FROM tbl_sys_menu m WHERE m.SID in (SELECT mr.MENU_SID F ...

  9. 【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 10—Advice for applying machine learning 机器学习应用建议

    Lecture 10—Advice for applying machine learning 10.1 如何调试一个机器学习算法? 有多种方案: 1.获得更多训练数据:2.尝试更少特征:3.尝试更多 ...

  10. c#服务器端控件confirm

    1>服务器端控件删除的数据的时候,可以调用js的confirm防止误操作,但是默认的样式实在是让人难以接受,怎么调用自定义的提示框而且同步回发到服务器端, 服务器端的控件的用linkbutton ...