当前位置: 代码迷 >> SQL >> iBATIS怎么复用SQL片段(翻译)
  详细解决方案

iBATIS怎么复用SQL片段(翻译)

热度:451   发布时间:2016-05-05 13:08:39.0
iBATIS如何复用SQL片段(翻译)

原文链接

http://opensource.atlassian.com/confluence/oss/display/IBATIS/How+do+I+reuse+SQL-fragments


When writing SqlMaps, you often encounter duplicate fragments of SQL, for example a FROM-clause or constraint-statement; iBATIS offers a simple yet powerful tag to reuse them. For the sake of simplicity, let's assume we want to get some items and we want to do a count on them.

Normally, you would write something like this:

当我们写SqlMaps的时候,经常会碰到重复的SQL片段,例如From语句或者约束条件;iBATIS提供了一个强大的标签来复用这些重复片段,简单举例,我们想检索一些字段,并且想统计它们。

通常情况下,你会这样写:

xml 代码
  1. <select?id="selectItemCount"?resultClass="int">?? ??
  2. ??SELECT?COUNT(*)?AS?total??? ??
  3. ??FROM?items??? ??
  4. ??WHERE?parentid?=?6?? ??
  5. select>?? ??
  6. <select?id="selectItems"?resultClass="Item">?? ??
  7. ??SELECT?id,?name??? ??
  8. ??FROM?items??? ??
  9. ??WHERE?parentid?=?6?? ??
  10. select>?? ??
  11. ??

?To eliminate this duplication, we use the tags 【sql】 and 【include】. The 【sql】-tag contains the fragment to reuse, the 【include】-tag to include such a fragment:

为了消除重复片段,我们使用【sql】和【include】标签。【sql】标签用来包含重复片段,【include】标签用来引入片段:

?xml 代码

  1. <sql?id="selectItem_fragment">?? ??
  2. ??FROM?items??? ??
  3. ??WHERE?parentid?=?6?? ??
  4. sql>?? ??
  5. <select?id="selectItemCount"?resultClass="int">?? ??
  6. ??SELECT?COUNT(*)?AS?total??? ??
  7. ??<include?refid="selectItem_fragment"/>?? ??
  8. select>?? ??
  9. <select?id="selectItems"?resultClass="Item">?? ??
  10. ??SELECT?id,?name??? ??
  11. ??<include?refid="selectItem_fragment"/>?? ??
  12. select>?? ??
  13. ??

?The 【include】-tag is namespace-aware so you can refer to fragments even when they are located in another map (however, due to the way iBATIS loads the SqlMaps, the included fragment should be loaded before the including statement).?

【inclued】标签是一个命名空间可知的,所以你可以引入其他map的片段.(但是,因为iBATIS引入SqlMap的顺序,被引入的片段,要优先于欲引入的sql部分被导入)

The fragments are included and processed on query-execution so parameters can be used too:

重复片段在查询执行时被引入和执行,所以参数依然可以使用:

?xml 代码

  1. <sql?id="selectItem_fragment">?? ??
  2. ??FROM?items??? ??
  3. ??WHERE?parentid?=?#value#??? ??
  4. sql>?? ??
  5. <select?id="selectItemCount"?parameterClass="int"?resultClass="int">?? ??
  6. ??SELECT?COUNT(*)?AS?total??? ??
  7. ??<include?refid="selectItem_fragment"/>?? ??
  8. select>?? ??
  9. <select?id="selectItems"?parameterClass="int"?resultClass="Item">?? ??
  10. ??SELECT?id,?name??? ??
  11. ??<include?refid="selectItem_fragment"/>?? ??
  12. select>?? ??
  13. ??
2 楼 edusaj 2006-12-16  
我觉得有实际意义至少我们项目现在的分页就有用,取记录数与明细之前的条件语句就相同,谢谢分享!
3 楼 deafwolf 2006-12-16  
edusaj 写道
我觉得有实际意义至少我们项目现在的分页就有用,取记录数与明细之前的条件语句就相同,谢谢分享!


我觉得楼主给的例子意义不大,但是在分页中用这个很不错,尤其是多条件查询,count和list分别写一个确实太麻烦
4 楼 joachimz 2006-12-16  
include还是使用很多的,除了例子中的count/list,还有相同的Mapping,不同的查询条件,在我们项目应用得非常多。
5 楼 sinokaka 2006-12-16  
我觉得例子仅仅是一个参考,主要是了解这个思路,知道这个功能,实际意义,对于我来说还是比较大的,我在网上找了很久才找到这个功能,看了SQL的官方文档这些都属于未记录(Document)的档案,所以就用我蹩脚的鸟语功夫,翻译了一下,希望对大家来说是一个参考
6 楼 stephen 2006-12-16  
要实现 SQL 的复用,最好是把 ajoo 的 JRC 和 iBatis 结合起来。
这可能要在 iBatis 底层进行修改,以提供更方便的使用接口。
目前还没认真想过如何结合,等遇到这样的需求时再看看。

ajoo 的 JRC:http://www.iteye.com/topic/21903
7 楼 znjq 2006-12-16  
include经常用,对于一些状态的判断还是挺方便的
8 楼 liuyxit 2006-12-16  
sinokaka 写道
我在网上找了很久才找到这个功能,看了SQL的官方文档这些都属于未记录(Document)的档案


怎么没记录!?
我下载的ibatis-2.3.0.677的iBATIS-SqlMaps-2_en.pdf就记录了。
9 楼 sinokaka 2006-12-16  
http://opensource.atlassian.com/confluence/oss/display/IBATIS/Not+Yet+Documented

我是在这里找到的,我在2.0里面的中文没有找到:)
10 楼 宏基小键盘 2006-12-16  
早就有这个功能了。而且用起来也非常方便。
11 楼 gilber 2006-12-21  
现在有一个问题:如果要取其他namespace里的SQL,好象不能指定namespace,就象这样会报错,请问谁知道怎么解决?
<sqlMap namespace="common">  <sql id="selectItem_fragment">          FROM items           WHERE parentid = 6        </sql></sqlMap><sqlMap namespace="test">        <select id="selectItems" resultClass="Item">          SELECT id, name           错误 <include refid="common.selectItem_fragment"/>     正确 <include refid="selectItem_fragment"/>             </select></sqlMap>
12 楼 sinokaka 2006-12-21  
在sqlmap-config中配置useStatementNamespaces="true"就可以了
13 楼 gilber 2006-12-21  
sinokaka 写道
在sqlmap-config中配置useStatementNamespaces="true"就可以了


原先没看到这一块,谢谢了!
14 楼 ddandyy 2006-12-22  
真的是很方便的  在实际中
至于说例子  好像没有几个例子是有意义的  主要就是用最简单的方式让别人明白怎么用就行了
15 楼 wdl123 2007-01-29  
<include refid="selectItem_fragment"/>     

在这个include里面可不可以放变量,从程序外面传进去
16 楼 小嘴看世界 2007-03-21  
<div class='code_title'>我感觉挺有用的,看我的代码</div>
<div class='code_title'/>
<div class='code_title'>xml 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-xml'>
    <li class='alt'><span><span class='tag'>&lt;</span><span class='tag-name'>statement</span><span>?</span><span class='attribute'>id</span><span>=</span><span class='attribute-value'>"search"</span><span>?</span><span class='attribute'>resultMap</span><span>=</span><span class='attribute-value'>"infoResult"</span><span class='tag'>&gt;</span><span>??</span></span></li>
    <li class=''><span>????????SELECT? ??</span></li>
    <li class='alt'><span>????????????lnid, ??</span></li>
    <li class=''><span>????????????tpye, ??</span></li>
    <li class='alt'><span>????????????dsc, ??</span></li>
    <li class=''><span>????????????pnid, ??</span></li>
    <li class='alt'><span>????????FROM?F48100? ??</span></li>
    <li class=''><span>????????</span><span class='tag'>&lt;</span><span class='tag-name'>include</span><span>?</span><span class='attribute'>refid</span><span>=</span><span class='attribute-value'>"Dy_SC"</span><span class='tag'>/&gt;</span><span>??</span></li>
    <li class='alt'><span>????????ORDER?BY?bcdat?DESC ??</span></li>
    <li class=''><span>????</span><span class='tag'>&lt;/</span><span class='tag-name'>statement</span><span class='tag'>&gt;</span><span>??</span></li>
</ol>
</div>
<p>?使用的时候include就OK了,如下</p>
<div class='code_title'>
<div class='code_title'>xml 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-xml'>
    <li class='alt'><span><span class='tag'>??? &lt;</span><span class='tag-name'>sql</span><span>?</span><span class='attribute'>id</span><span>=</span><span class='attribute-value'>"Dy_SC"</span><span class='tag'>&gt;</span><span>??</span></span></li>
    <li class=''><span>????????</span><span class='tag'>&lt;</span><span class='tag-name'>dynamic</span><span>?</span><span class='attribute'>prepend</span><span>=</span><span class='attribute-value'>"WHERE"</span><span class='tag'>&gt;</span><span>??</span></li>
    <li class='alt'><span>????????????</span><span class='tag'>&lt;</span><span class='tag-name'>isNotNull</span><span>?</span><span class='attribute'>prepend</span><span>=</span><span class='attribute-value'>"AND"</span><span>?</span><span class='attribute'>property</span><span>=</span><span class='attribute-value'>"pnid"</span><span class='tag'>&gt;</span><span>??</span></li>
    <li class=''><span>????????????????</span><span class='attribute'>pnid</span><span>?=?#pnid# ??</span></li>
    <li class='alt'><span>????????????</span><span class='tag'>&lt;/</span><span class='tag-name'>isNotNull</span><span class='tag'>&gt;</span><span>??</span></li>
    <li class=''><span>????????????</span><span class='tag'>&lt;</span><span class='tag-name'>isNotNull</span><span>?</span><span class='attribute'>prepend</span><span>=</span><span class='attribute-value'>"AND"</span><span>?</span><span class='attribute'>property</span><span>=</span><span class='attribute-value'>"dsc"</span><span class='tag'>&gt;</span><span>??</span></li>
    <li class='alt'><span>????????????????dsc?like?#dsc# ??</span></li>
    <li class=''><span>????????????</span><span class='tag'>&lt;/</span><span class='tag-name'>isNotNull</span><span class='tag'>&gt;</span><span>??</span></li>
    <li class='alt'><span>????????</span><span class='tag'>&lt;/</span><span class='tag-name'>dynamic</span><span class='tag'>&gt;</span><span>??</span></li>
    <li class=''><span>????</span><span class='tag'>&lt;/</span><span class='tag-name'>sql</span><span class='tag'>&gt;</span><span>??</span></li>
</ol>
</div>
</div>
<span class='tag'><span class='tag'><span class='tag'><span class='tag'><span class='tag'><span class='cdata'><span class='tag'><span class='tag'><span class='tag'>
<p>?</p>
<div class='code_title'>?</div>
<span class='tag'/></span></span></span></span></span></span></span></span></span>
17 楼 victor1017 2007-05-20  
测试了一下,刚开始没成功,说找不到要include的sql,后来发现我要include的sql放在了xml文件的最后,将他移到最前面就没问题了,所以大家要注意放置的顺序。
18 楼 lszone 2007-05-21  
谁说没用,我们现在就在用这种方法来做记录总数与记录明细的查询条件,节省了不少代码
19 楼 galaxystar 2007-05-21  
节省代码与提高代码可读性也是把双刃剑,
如果一个xml很大或者id不在一个配置中,你要复用这个id,查找也是一种成本.
并且,好像嵌套做得不好!

比如:

select * from (XX) where rownum <= 10

这里的XX到底是放include里还是select里?
一般XX是会变的,肯定是写在select里对应一个ibatis dao方法,那么include就难做了.
它不能传参数,不能嵌套.

比较丑陋的,就是 select * from ( 定义为一个include
而 ) where rownum <= 10定义为另一个include
20 楼 spiritfrog 2007-05-24  
sinokaka 写道
在sqlmap-config中配置useStatementNamespaces="true"就可以了

晕了,以前我怎么说namespace根本不起作用,不写也不会出错,原来还要这个配置。
21 楼 heartsong 2007-08-03  
还不错,不过如果大量使用的话,对于后来的开发人员阅读来说,可真是要痛苦了,就像在c语言里读goto一样。
  相关解决方案