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,这种“封闭”设计可以借鉴:
对外接口调用如下:
- 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对象。
- /**
- * Interface for getting data into, and out of a mapped statement
- */
- publicinterface TypeHandler {
- // para向第i个位置填充ps.
- public void setParameter(PreparedStatement ps,int i, Object parameter, String jdbcType)
- throws SQLException;
- // 根据rs结果集某字段名取值
- public Object getResult(ResultSet rs, String columnName)
- throws SQLException;
- public Object getResult(ResultSet rs, int columnIndex)
- throws SQLException;
- /**
- * Converts the String to the type that this handler deals with
- */
- public Object valueOf(String s);
- 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.
- publicinterface TypeHandlerCallback {
- public void setParameter(ParameterSetter setter, Object parameter)// 同上
- throws SQLException;
- public Object getResult(ResultGetter getter) // 同上
- throws SQLException;
- public Object valueOf(String s);
- }
StringTypeHandler——String类型帮助类
- publicclass StringTypeHandlerextends BaseTypeHandlerimplements TypeHandler {
- public void setParameter(PreparedStatement ps,int i, Object parameter, String jdbcType)
- throws SQLException {
- ps.setString(i, ((String) parameter));
- }
- public Object getResult(ResultSet rs, String columnName)
- throws SQLException {
- Object s = rs.getString(columnName); // 很熟悉的jdbc编程吧
- if (rs.wasNull()) {
- return null;
- } else {
- return s;
- }
- }
- public Object getResult(ResultSet rs, int columnIndex)
- throws SQLException {
- Object s = rs.getString(columnIndex);
- if (rs.wasNull()) {
- return null;
- } else {
- return s;
- }
- }
- }
最后“元数据”这块剩下最后一个Factory管理类:TypeHandlerFactory
- /**
- * Not much of a suprise, this is a factory class for TypeHandler objects.
- */
- publicclass TypeHandlerFactory {
- private final Map typeHandlerMap =new HashMap();// 用final Map来存储类型转换的帮助类
- private final TypeHandler unknownTypeHandler =new UnknownTypeHandler(this);
- private final HashMap typeAliases =new HashMap();// 保存type助记符,为什么呢?
- /**
- * Default constructor
- */
- public TypeHandlerFactory() {
- TypeHandler handler;
- handler = new BooleanTypeHandler();
- register(Boolean.class, handler);// 实际上把handler放入布尔值的map,然后再放入typeMap里。
- register(boolean.class, handler);
- handler = new ByteTypeHandler();
- register(Byte.class, handler);
- register(byte.class, handler);
- register(String.class,new StringTypeHandler());
- register(String.class,"CLOB", new CustomTypeHandler(newClobTypeHandlerCallback()));
- register(String.class,"LONGVARCHAR", new CustomTypeHandler(newClobTypeHandlerCallback()));
- register(byte[].class,new ByteArrayTypeHandler());
- register(byte[].class,"BLOB", new CustomTypeHandler(newBlobTypeHandlerCallback()));
- register(byte[].class,"LONGVARBINARY", new CustomTypeHandler(newBlobTypeHandlerCallback()));
- ....
- putTypeAlias("string", String.class.getName());
- putTypeAlias("byte", Byte.class.getName());
- putTypeAlias("long", Long.class.getName());
- ....
- }
- /* Public Methods */
- public TypeHandler getTypeHandler(Class type, String jdbcType) {
- Map jdbcHandlerMap = (Map) typeHandlerMap.get(type);
- TypeHandler handler = null;
- if (jdbcHandlerMap != null) {
- handler = (TypeHandler) jdbcHandlerMap.get(jdbcType);
- if (handler == null) {
- handler = (TypeHandler) jdbcHandlerMap.get(null);
- }
- }
- return handler;
- }
- /**
- * When in doubt, get the "unknown" type handler
- *
- * @return - if I told you, it would not be unknown, would it?
- */
- public TypeHandler getUnkownTypeHandler() {
- return unknownTypeHandler;
- }
- /**
- * Tells you if a particular class has a TypeHandler
- *
- * @param type - the class
- *
- * @return - true if there is a TypeHandler
- */
- public boolean hasTypeHandler(Class type) {
- return getTypeHandler(type) != null;
- }
- /**
- * Register (add) a type handler for a class and JDBC type
- *
- * @param type - the class
- * @param jdbcType - the JDBC type
- * @param handler - the handler instance
- */
- public void register(Class type, String jdbcType, TypeHandler handler) {
- Map map = (Map) typeHandlerMap.get(type);
- if (map == null) {
- map = new HashMap();
- typeHandlerMap.put(type, map);
- }
- map.put(jdbcType, handler);
- }
- /**
- * Lookup an aliased class and return it's REAL name
- *
- * @param string - the alias
- *
- * @return - the REAL name
- */
- public String resolveAlias(String string) {
- String key = null;
- if(string != null)
- key = string.toLowerCase();
- String value = null;
- if (typeAliases.containsKey(key)) {
- value = (String) typeAliases.get(key);
- } else {
- value = string;
- }
- return value;
- }
- /**
- * Adds a type alias that is case insensitive. All of the following String, string, StRiNg will equate to the same alias.
- * @param alias - the alias
- * @param value - the real class name
- */
- public void putTypeAlias(String alias, String value) {
- String key = null;
- if(alias != null)
- key = alias.toLowerCase();
- if (typeAliases.containsKey(key) && !typeAliases.get(key).equals(value)) {
- throw new SqlMapException("Error in XmlSqlMapClientBuilder. Alias name conflict occurred. The alias '" + key +"' is already mapped to the value '" + typeAliases.get(alias) +"'.");
- }
- typeAliases.put(key, value);
- }
- }
Mapping包
--parameter包意义——主要负责数据类型转换,把xml写的字符串映射成正确的类型,以上type包是解决了object到type的转换。
UML:
ParameterMap接口
- publicinterface ParameterMap {
- public String getId();
- public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters)
- throws SQLException;
- public Object[] getParameterObjectValues(RequestScope request, Object parameterObject);
- public CacheKey getCacheKey(RequestScope request, Object parameterObject);
- public void refreshParameterObjectValues(RequestScope request, Object parameterObject, Object[] values);
- public ParameterMapping[] getParameterMappings();
- public Class getParameterClass();
- }
ParameterMapping接口
- publicinterface ParameterMapping {
- public String getPropertyName();
- public boolean isOutputAllowed();
- }
BasicParameterMapping实现类:
- publicclass BasicParameterMappingimplements ParameterMapping {
- private staticfinal String MODE_INOUT ="INOUT";
- private staticfinal String MODE_OUT ="OUT";
- private staticfinal String MODE_IN ="IN";
- private String propertyName; // 从XML文件里读取需要转换的类型名
- private TypeHandler typeHandler; // 对象转换相应类型的工具map
- private String typeName; // this is used for REF types or user-defined types
- private int jdbcType;
- private String jdbcTypeName;
- private String nullValue;
- private String mode;
- private boolean inputAllowed;
- private boolean outputAllowed;
- private Class javaType; // 需要转换的类型class
- private String resultMapName; // 结果map名称
- private Integer numericScale;
- private String errorString;
- public BasicParameterMapping() {
- mode = "IN";
- inputAllowed = true;
- outputAllowed = false;
- }
- public void setJavaTypeName(String javaTypeName) {
- try {
- if (javaTypeName == null) {
- this.javaType = null;
- } else {// 通过getClassLoader().loadClass(className);来获得实例
- this.javaType = Resources.classForName(javaTypeName);
- }
- } catch (ClassNotFoundException e) {
- throw new SqlMapException("Error setting javaType property of ParameterMap. Cause: " + e, e);
- }
- }
- }
BasicParameterMap实现类
- publicclass BasicParameterMapimplements ParameterMap {
- private String id;
- private Class parameterClass;
- private ParameterMapping[] parameterMappings;
- private DataExchange dataExchange;
- private String resource;
- private Map parameterMappingIndex = new HashMap();
- private SqlMapExecutorDelegate delegate;
- public void setParameterMappingList(List parameterMappingList) {
- this.parameterMappings = (BasicParameterMapping[]) parameterMappingList.toArray(newBasicParameterMapping[parameterMappingList.size()]);
- for (int i =0; i < parameterMappings.length; i++) {
- parameterMappingIndex.put(parameterMappings[i].getPropertyName(),new Integer(i));
- }
- Map props = new HashMap();
- props.put("map",this);
- dataExchange = delegate.getDataExchangeFactory().getDataExchangeForClass(parameterClass);
- dataExchange.initialize(props);
- }
- /**
- * @param ps
- * @param parameters
- * @throws java.sql.SQLException
- */
- public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters)
- throws SQLException {
- ErrorContext errorContext = request.getErrorContext();
- errorContext.setActivity("applying a parameter map");
- errorContext.setObjectId(this.getId());
- errorContext.setResource(this.getResource());
- errorContext.setMoreInfo("Check the parameter map.");
- if (parameterMappings != null) {
- for (int i =0; i < parameterMappings.length; i++) {
- BasicParameterMapping mapping = (BasicParameterMapping) parameterMappings[i];
- errorContext.setMoreInfo(mapping.getErrorString());
- if (mapping.isInputAllowed()) {
- setParameter(ps, mapping, parameters, i);
- }
- }
- }
- }
- public Object[] getParameterObjectValues(RequestScope request, Object parameterObject) {
- return dataExchange.getData(request, this, parameterObject);
- }
- public CacheKey getCacheKey(RequestScope request, Object parameterObject) {
- return dataExchange.getCacheKey(request, this, parameterObject);
- }
- public void refreshParameterObjectValues(RequestScope request, Object parameterObject, Object[] values) {
- dataExchange.setData(request, this, parameterObject, values);
- }
- protected void setParameter(PreparedStatement ps, BasicParameterMapping mapping, Object[] parameters,int i) throws SQLException {
- Object value = parameters[i];
- // Apply Null Value
- String nullValueString = mapping.getNullValue();
- if (nullValueString != null) {
- TypeHandler handler = mapping.getTypeHandler();
- if (handler.equals(value, nullValueString)) {
- value = null;
- }
- }
- // Set Parameter
- TypeHandler typeHandler = mapping.getTypeHandler();
- if (value != null) {
- typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());
- } else if (typeHandlerinstanceof CustomTypeHandler) {
- typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());
- } else {
- int jdbcType = mapping.getJdbcType();
- if (jdbcType != JdbcTypeRegistry.UNKNOWN_TYPE) {
- ps.setNull(i + 1, jdbcType);
- } else {
- ps.setNull(i + 1, Types.OTHER);
- }
- }
- }
- }
ibatis源码学习3_源码包结构的更多相关文章
- 【 js 基础 】【 源码学习 】源码设计 (持续更新)
学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析第二部分:undersc ...
- 【 js 基础 】【 源码学习 】源码设计 (更新了backbone分析)
学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析 第二部分:unders ...
- jquery源码学习(一)——jquery结构概述以及如何合适的暴露全局变量
jQuery 源码学习是对js的能力提升很有帮助的一个方法,废话不说,我们来开始学习啦 我们学习的源码是jquery-2.0.3已经不支持IE6,7,8了,因为可以少学很多hack和兼容的方法. jq ...
- USB2.0协议学习笔记---USB数据包结构
USB包类型和传输过程 USB是一种串行总线,因此数据都是一位一位传输的,如同串口那样,但是USB在真实物理电路上却不是TTL电平,而是一种差分信号采用NRZI编码,就是用变化表示0,不变表示1,同 ...
- Vue2.x源码学习笔记-源码目录结构整理
先从github上下载或者clone一个vue分支项目 https://github.com/vuejs/vue 查看下目录结果 先列出一些目录 Vue |— build 打包相关的配置文件,其中最重 ...
- springFramework 源码学习之源码下载与编译
1.源码下载 Spring已经将源码从svn迁移到了git.对于习惯了svn的人来说依然可以svn checkout,最好checkout到英文路径下,本人中文路径编译不过,具体原因不明,路径: ht ...
- VUE 源码学习01 源码入口
VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...
- vue 源码学习(一) 目录结构和构建过程简介
Flow vue框架使用了Flow作为类型检查,来保证项目的可读性和维护性.vue.js的主目录下有Flow的配置.flowconfig文件,还有flow目录,指定了各种自定义类型. 在学习源码前可以 ...
- async源码学习 - 全部源码
因为工作需要,可能我离前端走远了,偏node方向了.所以异步编程的需求很多,于是乎,不得不带着学习async了. 我有个习惯,用别人的东西之前,喜欢稍微搞明白点,so就带着看看其源码. github: ...
随机推荐
- python开发_python中的list操作
对python中list的操作,大家可以参考: Python list 操作 以下是我个人的笔记: ============================================ Add b ...
- [转] C#2010 在TreeView控件下显示路径下所有文件和文件夹
原文 张丹-小桥流水,C#2010 在TreeView控件下显示路径下所有文件和文件夹 C#2010学习过程中有所收获,便总结下来,希望能给和我一样在学习遇到困难的同学提供参考. 本文主要介绍两个自定 ...
- 用django实现redirect的几种方法总结
用django开发web应用, 经常会遇到从一个旧的url转向一个新的url.这种隐射也许有规则,也许没有.但都是为了实现业务的需要.总体说来,有如下几种方法实现 django的 redirect.1 ...
- Spring Boot实践——Filter实现
Filter介绍 Filter是Servlet规范规定的,不属于spring框架,也是用于请求的拦截.但是它适合更粗粒度的拦截,在请求前后做一些编解码处理.日志记录等. 一个Filter包括:1).在 ...
- Sass 入门 (一) 安装Sass
Sass安装 ruby安装 因为sass依赖于ruby环境,所以装sass之前先确认装了ruby.先导官网下载个ruby 在安装的时候,请勾选Add Ruby executables to your ...
- springMVC环境搭建(1)
工作一年以来,写的都是.net,最近比较闲,想把之前学过的java相关的东西捡起来,也学点新的东西.以前做过SSH架构,一直好奇spring mvc是怎么样的,所以今天试试看. 总体的代码结构 手动输 ...
- aop中的顾问
通知只能指定织入的时间点,目标方法之前,之后,环绕,还是异常时. 要想指定切入点就要使用顾问
- aop中通知详情
- 深度学习篇——Tensorflow配置(傻瓜安装模式)
前言 如果你是一个完美主义者,那么请绕过此文,请参考<深度学习篇——Tensorflow配置(完美主义模式)> 安装 pip install tensorflow ok,只要不报错,安装就 ...
- 第五章 大数据平台与技术 第12讲 大数据处理平台Spark
Spark支持多种的编程语言 对比scala和Java编程上节课的计数程序.相比之下,scala简洁明了. Hadoop的IO开销大导致了延迟高,也就是说任务和任务之间涉及到I/O操作.前一个任务完成 ...