• ibatis源码学习3_源码包结构


    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,这种“封闭”设计可以借鉴:

    对外接口调用如下:

    Java代码  收藏代码
    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对象。

    Java代码  收藏代码
    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); 

    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.

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

    StringTypeHandler——String类型帮助类

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

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

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

    Mapping包

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

        UML:

    ParameterMap接口

    Java代码  收藏代码
    1. publicinterface ParameterMap { 
    2.  
    3.   public String getId(); 
    4.  
    5.   public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters) 
    6.       throws SQLException; 
    7.  
    8.   public Object[] getParameterObjectValues(RequestScope request, Object parameterObject); 
    9.  
    10.   public CacheKey getCacheKey(RequestScope request, Object parameterObject); 
    11.  
    12.   public void refreshParameterObjectValues(RequestScope request, Object parameterObject, Object[] values); 
    13.  
    14.   public ParameterMapping[] getParameterMappings(); 
    15.  
    16.   public Class getParameterClass(); 
    17.  

    ParameterMapping接口

    Java代码  收藏代码
    1. publicinterface ParameterMapping { 
    2.  
    3.   public String getPropertyName(); 
    4.  
    5.   public boolean isOutputAllowed(); 
    6.  

    BasicParameterMapping实现类:

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

    BasicParameterMap实现类

    Java代码  收藏代码
      1. publicclass BasicParameterMapimplements ParameterMap { 
      2.  
      3.   private String id; 
      4.   private Class parameterClass; 
      5.  
      6.   private ParameterMapping[] parameterMappings; 
      7.   private DataExchange dataExchange; 
      8.  
      9.   private String resource; 
      10.  
      11.   private Map parameterMappingIndex = new HashMap(); 
      12.   private SqlMapExecutorDelegate delegate; 
      13.  
      14.  
      15.   public void setParameterMappingList(List parameterMappingList) { 
      16.     this.parameterMappings = (BasicParameterMapping[]) parameterMappingList.toArray(newBasicParameterMapping[parameterMappingList.size()]); 
      17.     for (int i =0; i < parameterMappings.length; i++) { 
      18.       parameterMappingIndex.put(parameterMappings[i].getPropertyName(),new Integer(i)); 
      19.     } 
      20.     Map props = new HashMap(); 
      21.     props.put("map",this); 
      22.  
      23.     dataExchange = delegate.getDataExchangeFactory().getDataExchangeForClass(parameterClass); 
      24.     dataExchange.initialize(props); 
      25.   } 
      26.  
      27.   /**
      28.    * @param ps
      29.    * @param parameters
      30.    * @throws java.sql.SQLException
      31.    */ 
      32.   public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters) 
      33.       throws SQLException { 
      34.  
      35.     ErrorContext errorContext = request.getErrorContext(); 
      36.     errorContext.setActivity("applying a parameter map"); 
      37.     errorContext.setObjectId(this.getId()); 
      38.     errorContext.setResource(this.getResource()); 
      39.     errorContext.setMoreInfo("Check the parameter map."); 
      40.  
      41.     if (parameterMappings != null) { 
      42.       for (int i =0; i < parameterMappings.length; i++) { 
      43.         BasicParameterMapping mapping = (BasicParameterMapping) parameterMappings[i]; 
      44.         errorContext.setMoreInfo(mapping.getErrorString()); 
      45.         if (mapping.isInputAllowed()) { 
      46.           setParameter(ps, mapping, parameters, i); 
      47.         } 
      48.       } 
      49.     } 
      50.   } 
      51.  
      52.   public Object[] getParameterObjectValues(RequestScope request, Object parameterObject) { 
      53.     return dataExchange.getData(request, this, parameterObject); 
      54.   } 
      55.  
      56.   public CacheKey getCacheKey(RequestScope request, Object parameterObject) { 
      57.     return dataExchange.getCacheKey(request, this, parameterObject); 
      58.   } 
      59.  
      60.   public void refreshParameterObjectValues(RequestScope request, Object parameterObject, Object[] values) { 
      61.     dataExchange.setData(request, this, parameterObject, values); 
      62.   } 
      63.  
      64.   protected void setParameter(PreparedStatement ps, BasicParameterMapping mapping, Object[] parameters,int i) throws SQLException { 
      65.     Object value = parameters[i]; 
      66.     // Apply Null Value 
      67.     String nullValueString = mapping.getNullValue(); 
      68.     if (nullValueString != null) { 
      69.       TypeHandler handler = mapping.getTypeHandler(); 
      70.       if (handler.equals(value, nullValueString)) { 
      71.         value = null; 
      72.       } 
      73.     } 
      74.  
      75.     // Set Parameter 
      76.     TypeHandler typeHandler = mapping.getTypeHandler(); 
      77.     if (value != null) { 
      78.       typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName()); 
      79.     } else if (typeHandlerinstanceof CustomTypeHandler) { 
      80.       typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName()); 
      81.     } else { 
      82.       int jdbcType = mapping.getJdbcType(); 
      83.       if (jdbcType != JdbcTypeRegistry.UNKNOWN_TYPE) { 
      84.         ps.setNull(i + 1, jdbcType); 
      85.       } else { 
      86.         ps.setNull(i + 1, Types.OTHER); 
      87.       } 
      88.     } 
      89.   } 
      90.  
  • 相关阅读:
    58) Gitlab加入LDAP认证 (windows AD)
    57) 《乌合之众》读书笔记【1】
    56) 监控系统简单介绍
    前端学习建议汇总(留着自己看的心灵鸡汤)
    vscode分享代码插件Polacode
    PHP论坛实现积分系统的思路
    thinkphp删除图片的方法实现
    php高并发问题解决思路
    PHP和Thinkphp模拟留言板,应对XSS攻击(超完整!)
    sql server特殊字符查询问题及ESCAPE的使用
  • 原文地址:https://www.cnblogs.com/doudouxiaoye/p/5694211.html
Copyright © 2020-2023  润新知