- 浏览: 957294 次
- 性别:
- 来自: 江西上饶
文章分类
- 全部博客 (460)
- p.spring (56)
- p.maven (20)
- p.ant (17)
- p.jee (18)
- p.jse (33)
- p.ofbiz (31)
- p.软件工程 (8)
- p.struts2 (5)
- p.hibernate (5)
- linux (25)
- 设计模式 (2)
- p.javascript (11)
- 硬件 (1)
- p.jsp (2)
- p.windows批处理 (1)
- 操作系统问题 (5)
- 算法 (1)
- p.mysql (7)
- p.sql (5)
- p.c (1)
- google产品 (0)
- 内存 (1)
- p.struts (1)
- p.freemarker (7)
- p.css (4)
- p.log4j (10)
- p.html (3)
- 淘宝产品 (0)
- 其他 (3)
- 编译器 (0)
- svn (4)
- p.spring.security (11)
- 图形 (0)
- p.xml (1)
- p.ssh (0)
- p.jquery (4)
- p.jdbc (3)
- p.flex (0)
- p.c++ (0)
- p.c#Net (0)
- p.assembly (0)
- p.sqlserver (0)
- p.其他 (3)
- p.webwork (21)
- p.wap (12)
- p.cglib (1)
- p.jee服务器 (11)
- windows (2)
- p.iphone (1)
- p.java.分布式与集群 (2)
- p.ibatis (16)
- p.eclipse (5)
- 架构 (2)
- http协议 (5)
- 我的个人标准 (2)
- 多线程 (1)
- 奇怪问题 (5)
- p.jira (13)
- p.httpclient (1)
- 服务器.apache (11)
- 安全防范 (1)
- p.PODAM (1)
- p.junit (16)
- fop (2)
- 硬盘安装 (1)
- powerdesigner (0)
- 单元测试 (1)
- apache commons (4)
- tomcat+apache集群 (10)
- 各类诡辩 (1)
- 安卓 (8)
- qvod (1)
- java编程基础知识考试考点及答案 (0)
- 工作总结 (4)
- oracle (0)
- spring的util工具 (3)
- json (2)
- maven (3)
- jms (19)
- p.bat (3)
- hadoop (2)
- git (3)
- nginx (1)
- p.移动开发 (1)
- shiro (3)
- 游戏破解 (1)
- react-native (7)
- ios开发 (1)
- webmagic (6)
- socks5 (1)
最新评论
-
weituotian:
说的不好,没人看的
公司系统中的菜单功能和权限功能 -
石不易:
非常详细的注解~
绑定端口和IP,Listen 与VirtualHost指令 -
spring_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
spring mvc -
liyixing1:
PandaDONG 写道谢谢你啊,我已经下下来了,只是还有很多 ...
jira war安装 -
liyixing1:
PandaDONG 写道谢谢你啊,我已经下下来了,只是还有很多 ...
jira war安装
位于包
com.ibatis.sqlmap.engine.mapping.sql.dynamic
。ibatis的标签和mybatis的标签之间,区别已经很大了
ibatis在启动的时候,会把所有的sql对象解析出来,并初始化为对应的实际实现。Sql对象的实现类有很多,常见的有
StaticSql,这个是纯净态的,没有动态SQL
DynamicSql是包含了动态标签的SQL对象。
理解了动态SQL其他都是类似原理。
如上配置的一个sql语句,第一层节点有三个,text,dynamic元素,text(这个属于XML的知识,具体从XML脑补)。
在调用该SQL的时候,会执行是DynamicSql的
process方法
比较重要的方法
dynamic元素有三个属性
prepend="where" open="" close=""
prepend和open是在DynamicTagHandler的doStartFragment和doPrepend共同完成处理,close是在doEndFragment处理的。
由于dynamic包含了isNotEmpty,因此在dynamic处理之前,需要处理isNotEmpty,
isNotEmpty之前的处理是和dynamic类似的。
isNotEmpty的doPrepend方法是BaseTagHandler的,并没有改写
com.ibatis.sqlmap.engine.mapping.sql.dynamic
。ibatis的标签和mybatis的标签之间,区别已经很大了
ibatis在启动的时候,会把所有的sql对象解析出来,并初始化为对应的实际实现。Sql对象的实现类有很多,常见的有
StaticSql,这个是纯净态的,没有动态SQL
DynamicSql是包含了动态标签的SQL对象。
理解了动态SQL其他都是类似原理。
<select id="selectOutSales" resultClass="hashmap"> SELECT t_tz_btscxx.BTSCID, t_tz_btscxx.SZTZDID, t_tz_btscxx.TZSXH, t_tz_btscxx.RTSJ, t_tz_btscxx.RTSL, t_tz_btscxx.SCLXDM, t_tz_btscxx.RTSCX, t_tz_btscxx.ZZL, t_tz_btscxx.SCZT, t_tz_btscxx.SFWCTZ, t_tz_btscxx.WCTZSJ, t_tz_btscxx.CJRY, t_tz_btscxx.CJRQ, t_tz_btscxx.XGRY, t_tz_btscxx.XGRQ, t_tz_btscxx.SCBJ FROM t_tz_btscxx <dynamic prepend="where"> <isNotEmpty prepend="and" property="BTSCID"> BTSCID like '%$BTSCID$%' </isNotEmpty> </dynamic> </select>
如上配置的一个sql语句,第一层节点有三个,text,dynamic元素,text(这个属于XML的知识,具体从XML脑补)。
在调用该SQL的时候,会执行是DynamicSql的
process方法
private void process(StatementScope statementScope, Object parameterObject) { SqlTagContext ctx = new SqlTagContext(); List localChildren = children; processBodyChildren(statementScope, ctx, parameterObject, localChildren.iterator()); ParameterMap map = new ParameterMap(delegate); map.setId(statementScope.getStatement().getId() + "-InlineParameterMap"); map.setParameterClass(((MappedStatement) statementScope.getStatement()).getParameterClass()); map.setParameterMappingList(ctx.getParameterMappings()); String dynSql = ctx.getBodyText(); // Processes $substitutions$ after DynamicSql if (SimpleDynamicSql.isSimpleDynamicSql(dynSql)) { dynSql = new SimpleDynamicSql(delegate, dynSql).getSql(statementScope, parameterObject); } statementScope.setDynamicSql(dynSql); statementScope.setDynamicParameterMap(map); }
比较重要的方法
//这是处理SQL内部各个节点的方法 private void processBodyChildren(StatementScope statementScope, SqlTagContext ctx, Object parameterObject, Iterator localChildren, PrintWriter out) { //每个节点都需要被处理 while (localChildren.hasNext()) { SqlChild child = (SqlChild) localChildren.next(); //纯文本节点,处理比较简单,就是把参数等解析出来。 if (child instanceof SqlText) { SqlText sqlText = (SqlText) child; String sqlStatement = sqlText.getText(); if (sqlText.isWhiteSpace()) { out.print(sqlStatement); } else if (!sqlText.isPostParseRequired()) { // BODY OUT out.print(sqlStatement); ParameterMapping[] mappings = sqlText.getParameterMappings(); if (mappings != null) { for (int i = 0, n = mappings.length; i < n; i++) { ctx.addParameterMapping(mappings[i]); } } } else { IterateContext itCtx = ctx.peekIterateContext(); if(null != itCtx && itCtx.isAllowNext()){ itCtx.next(); itCtx.setAllowNext(false); if(!itCtx.hasNext()) { itCtx.setFinal(true); } } if(itCtx!=null) { StringBuffer sqlStatementBuffer = new StringBuffer(sqlStatement); iteratePropertyReplace(sqlStatementBuffer, itCtx); sqlStatement = sqlStatementBuffer.toString(); } sqlText = PARAM_PARSER.parseInlineParameterMap(delegate.getTypeHandlerFactory(), sqlStatement); ParameterMapping[] mappings = sqlText.getParameterMappings(); out.print(sqlText.getText()); if (mappings != null) { for (int i = 0, n = mappings.length; i < n; i++) { ctx.addParameterMapping(mappings[i]); } } } } else if (child instanceof SqlTag) { //节点本身就是一个节点。每种节点都有自己的显示,每个节点实际上用的是SqlTag,一种Tag的子类。内部包含了SqlTagHandler,每个SqlTag都会初始化自己的处理器。对于dynamic使用的是DynamicTagHandler SqlTag tag = (SqlTag) child; SqlTagHandler handler = tag.getHandler(); int response = SqlTagHandler.INCLUDE_BODY; do { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); //这句比较重要,对于条件标签,如果条件不满足,会返回SKIP_BODY,来跳过该元素处理 response = handler.doStartFragment(ctx, tag, parameterObject); if (response != SqlTagHandler.SKIP_BODY) { processBodyChildren(statementScope, ctx, parameterObject, tag.getChildren(), pw); pw.flush(); pw.close(); StringBuffer body = sw.getBuffer(); response = handler.doEndFragment(ctx, tag, parameterObject, body); handler.doPrepend(ctx, tag, parameterObject, body); if (response != SqlTagHandler.SKIP_BODY) { if (body.length() > 0) { out.print(body.toString()); } } } } while (response == SqlTagHandler.REPEAT_BODY); ctx.popRemoveFirstPrependMarker(tag); if(ctx.peekIterateContext()!= null && ctx.peekIterateContext().getTag() == tag) { ctx.setAttribute(ctx.peekIterateContext().getTag(), null); ctx.popIterateContext(); } } } }
dynamic元素有三个属性
prepend="where" open="" close=""
prepend和open是在DynamicTagHandler的doStartFragment和doPrepend共同完成处理,close是在doEndFragment处理的。
public class DynamicTagHandler extends BaseTagHandler { public int doStartFragment(SqlTagContext ctx, SqlTag tag, Object parameterObject) { //DynamicTagHandler的doStartFragment只是负责把RemoveFirstPrependMarker标记对象创建和压入。 ctx.pushRemoveFirstPrependMarker(tag); return BaseTagHandler.INCLUDE_BODY; } }
public void pushRemoveFirstPrependMarker(SqlTag tag) { if(tag.getHandler() instanceof DynamicTagHandler) { //对于DynamicTagHandler之类的条件标签,如果开启了prepend属性,需要设置标记为true。这会造成之后的条件语句的改变,即当出现过一个条件满足时,之后的条件的prepend才会有效,而DynamicTagHandler本身的prepend也才会生效。 对于只有条件,而没有对应的上级(select 标签元素等不是上级),只要满足了条件,那么就会追加prepend,而不管具体是不是第一次满足。 // this was added to retain default behavior if(tag.isPrependAvailable()) { removeFirstPrependStack.addFirst( new RemoveFirstPrependMarker(tag,true)); } else { removeFirstPrependStack.addFirst( new RemoveFirstPrependMarker(tag,false)); } } else if("true".equals(tag.getRemoveFirstPrepend()) || "iterate".equals(tag.getRemoveFirstPrepend())){ // you must be specific about the removal otherwise it // will function as ibatis has always functioned and add // the prepend removeFirstPrependStack.addFirst( new RemoveFirstPrependMarker(tag,true)); } else if(!tag.isPrependAvailable() && !"true".equals(tag.getRemoveFirstPrepend()) && !"iterate".equals(tag.getRemoveFirstPrepend()) && tag.getParent() != null) { // if no prepend or removeFirstPrepend is specified // we need to look to the parent tag for default values if("true".equals(tag.getParent().getRemoveFirstPrepend()) || "iterate".equals(tag.getParent().getRemoveFirstPrepend())) { removeFirstPrependStack.addFirst( new RemoveFirstPrependMarker(tag,true)); } } else { removeFirstPrependStack.addFirst( new RemoveFirstPrependMarker(tag,false)); } }
由于dynamic包含了isNotEmpty,因此在dynamic处理之前,需要处理isNotEmpty,
isNotEmpty之前的处理是和dynamic类似的。
isNotEmpty的doPrepend方法是BaseTagHandler的,并没有改写
public void doPrepend(SqlTagContext ctx, SqlTag tag, Object parameterObject, StringBuffer bodyContent) { //可以看到open属性是先于prepend属性处理的。但是每次sql字符插入都是从0位置插入,所以open先处理,但是当open和prepend都存在,prepend会插入到open之前的位置。 if (tag.isOpenAvailable() && !(tag.getHandler() instanceof IterateTagHandler)) { if (bodyContent.toString().trim().length() > 0) { bodyContent.insert(0, tag.getOpenAttr()); } } if (tag.isPrependAvailable()) { if (bodyContent.toString().trim().length() > 0) { //这里看到对于标记是true的,那么第一次不进行追加 //ctx.peekRemoveFirstPrependMarker(tag)取的是堆栈的第二个数据,而不是最顶部的数据。如上的配置,当处理IsNotEmpty的时候,取得是它的父级dynamic的设置。 //实际上ibatis的实现者把父级也看成和子元素一样的的平行级别处理了, P--- C---1 C---2 变成了 C---1 C---2 P--- 的结构,那么当C--1满足,C1不进行住家prepend,而C--2和P--则需要。 if (tag.getParent() != null && ctx.peekRemoveFirstPrependMarker(tag)) { ctx.disableRemoveFirstPrependMarker(); }else { bodyContent.insert(0, tag.getPrependAttr()); } } } }
发表评论
-
深入了解MyBatis参数
2017-05-04 21:12 381深入了解MyBatis参数 http://blog.csdn ... -
MyBatis Generator 详解
2015-08-03 14:00 760http://blog.csdn.net/isea533/ar ... -
枚举 enum
2013-12-13 17:28 2588当使用枚举时,需要使用EnumTypeHandler或者Enu ... -
mybatis generator tools配置文件解析
2012-12-20 23:28 25408这是mybatis3 generator 配 ... -
问题解决方案
2011-08-22 00:25 24191.Mapped Statements collection ... -
mybatis的参数
2011-06-16 12:36 6427在类DynamicSqlSource 方法 public Bo ... -
与spring结合
2011-05-20 21:58 1235实体省略 maping文件省略 dao接口省略 mybatis ... -
动态sql
2011-05-05 17:54 1258ibatis支持动态的组合sql。 包括动态元素 if ... -
ibatis缓存
2011-05-05 16:38 4505ibatis的session缓存。做了一个测试 <?xm ... -
ibatis官方推荐目录结构
2011-05-05 13:24 1053src/com.liyixing.application.da ... -
sql映射文件
2011-04-30 22:09 2551<?xml version="1.0" ... -
配置文件
2011-04-30 20:17 1802mybatis的配置文件结构 顶级是configuration ... -
session的getMapper方法解析
2011-04-30 17:22 9636跟踪: DefaultSqlSession类 public & ... -
一个简单例子,以及基于接口,class对象调用
2011-04-30 16:59 1322应用结构: IbatisConfiguration.xm ... -
范围和声明周期(对象声明周期)
2011-04-29 23:19 1344先看mybatis用户手册中的一段代码 DataSource ...
相关推荐
iBatis动态SQL标签用法 iBatis是Java持久层框架,提供了动态SQL标签来实现动态查询。动态SQL标签可以根据不同的条件生成不同的SQL语句,从而提高查询效率和灵活性。 动态SQL片段 iBatis提供了动态SQL片段的功能,...
转ibatis动态sql - phoebus0501 - 博客园.mht
IBATIS动态sql - 紫晶幻治 - 51CTO技术博客.mht
iBATIS 的核心在于POJO(Plain Old Java Object)与SQL之间的映射关系,而不是自动生成SQL语句。这意味着开发者需要手动编写SQL,然后通过配置文件将SQL的参数和返回结果映射到对应的Java对象。 iBATIS 提供了灵活...
### iBatis中的动态SQL语句详解 #### 引言 在进行数据库操作时,我们经常需要根据不同的条件构建不同的SQL语句。这种需求在实际开发中极为常见,尤其是在处理复杂的查询逻辑时。iBatis(现在通常被称为MyBatis)...
在探讨ibatis中的动态SQL(Dynamic SQL)及`prepend`的使用时,我们首先需要对ibatis有一个基本的理解。ibatis是一种开源的数据访问层框架,它简化了Java应用程序与数据库之间的交互过程。通过使用XML配置文件来定义...
5. **动态SQL**:讲解如何使用iBATIS的动态元素来构建灵活的SQL语句,以应对复杂的查询需求。 6. **API使用**:介绍SqlSession、SqlSessionFactory、Executor等关键接口和类的使用方法。 7. **缓存机制**:解释...
### iBATIS-SqlMaps2入门代码文档知识点详解 #### 一、简介 iBATIS-SqlMaps2是一款用于简化Java应用程序与数据库交互过程的框架。该框架通过配置文件定义了对象关系映射规则,使得开发者能够更加专注于业务逻辑而...
iBATIS-SqlMaps-2-Tutorial_cniBATIS-SqlMaps-2-Tutorial_cn.pdf.pdfiBATIS-SqlMaps-2-Tutorial_cn.pdfiBATIS-SqlMaps-2-Tutorial_cn.pdf
对于Ibatis,这是一个轻量级的持久层框架,它将SQL语句与Java代码分离,提供了动态SQL的能力。在默认情况下,Ibatis并不会自动打印执行的SQL语句,但通过配置,我们可以使Ibatis在运行时输出SQL,这对于调试和性能...
此外,教程还会涵盖动态SQL,这是IBATIS的一大亮点,允许在运行时构建和修改SQL语句,提高了代码的复用性和可维护性。 在使用IBATIS的过程中,你可能会遇到参数映射和结果映射的问题。《ibatis-sqlmaps-2_cn》将...
[iBATIS]sql转换工具 简单哦~ 项目组自己写的哦~分享给大家了
5. **动态SQL**:iBATIS的一大亮点是其强大的动态SQL能力,可以实现条件查询、循环拼接SQL等复杂逻辑,无需编写大量Java代码。 6. **Mapper接口**:iBATIS 2.3版本引入了Mapper接口,将XML配置与Java代码更好地结合...
iBATIS,作为一款优秀的持久层框架,提供了强大的动态SQL功能,解决了直接使用JDBC时编写复杂动态SQL的难题。本文将深入探讨iBATIS动态注入的相关知识点。 iBATIS动态SQL主要通过XML映射文件中的特定标签实现,允许...
iBATIS允许直接在SQL语句中处理复杂的查询和事务管理,同时提供了一种动态和灵活的方式来映射结果集到Java对象。 【SQL Server 2000】:这是微软发布的关系型数据库管理系统,主要用于存储、管理和检索数据。SQL ...
生成数据库表结构: 根据解析得到的SQL语句中的表名、字段名、数据类型等信息,动态地生成相应的数据库表结构。这可以通过编程语言与数据库操作的API来实现,比如Java中的JDBC或者MyBatis/iBatis提供的API。 执行SQL...
动态SQL是iBATIS的一大特色,它允许在SQL语句中使用条件判断、循环等逻辑,极大地增强了SQL的灵活性。 本书首先会引导读者理解iBATIS的基本架构,然后详细介绍如何创建和配置SqlMap,以及如何编写映射文件。映射...
在使用iBatis(现为MyBatis)作为持久层框架进行开发时,有时我们需要调试SQL语句,以便查看执行的SQL、优化性能或者解决查询问题。本文将详细讲解如何在iBatis日志信息中打印SQL语句,以便更好地理解和优化数据库...
iBATIS-SqlMaps ibatis入门教程,教你如何做配置ibatis