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. 【转】C#中Func与Action的理解

    原文地址:https://www.cnblogs.com/ultimateWorld/p/5608122.html Action 与 Func是.NET类库中增加的内置委托,以便更加简洁方便的使用委托 ...

  2. Deep Learning 阅读笔记:Convolutional Auto-Encoders 卷积神经网络的自编码表达

    需要搭建一个比较复杂的CNN网络,希望通过预训练来提高CNN的表现. 上网找了一下,关于CAE(Convolutional Auto-Encoders)的文章还真是少,勉强只能找到一篇瑞士的文章. S ...

  3. ThinkPHP自动令牌验证(附实例)

    一.数据表结构 user表结构如下: id username password 二.view模板部分 /view/index.html页面如下:   1 2 3 4 5 6 <form acti ...

  4. 「小程序JAVA实战」小程序多媒体组件(27)

    转自:https://idig8.com/2018/08/19/xiaochengxujavashizhanxiaochengxuduomeitizujian27/ 来说下 ,小程序的多媒体组件.源码 ...

  5. 查看DNS服务器

    电脑右键查看本地连接 查看状态 然后看DNS

  6. angularjs学习访问服务器(5)

    (1) 后台AngularController.java代码 package com.amy.controller; import java.util.ArrayList; import java.u ...

  7. Spring事务管理API

  8. php-yii-form标签

    yii 标签用法(模板) (2013-08-14 17:28:19) 转载▼ 标签: it 分类: yii yii模板中的label标签 <?php echo $form->labelEx ...

  9. 【祥哥带你玩HoloLens开发】了解如何实现远程主机为HoloLens实时渲染

    今天有一个兄弟在群里讲到他们的项目模型比较大,单用HoloLens运行设备的性能无法满足需要,问道如何将渲染工作交给服务器来做,讲渲染结果传给HoloLens.正好刚刚看官方github的时候发现一个 ...

  10. MongoDB 那些坑

    MongoDB 是目前炙手可热的 NoSQL 文档型数据库,它提供的一些特性很棒:如自动 failover 机制,自动 sharding,无模式 schemaless,大部分情况下性能也很棒.但是薄荷 ...