本来我也不喜欢iBatis,那是由于我当时还不怎么会用它,如今我想说,iBatis是个好东西,不信你试试看。以下是我在项目实践中对iBatis的一个小总结。希望帮助众多在疲于iBatis编码而无暇思考的苦工们找到一些偷懒的机会。

 
SqlMap的配置是iBatis中应用的核心。这部分任务占领了iBatis开发的70的工作量。


1、命名空间:
  <sqlMap namespace="Account">。在此空间外要引用此空间的元素,则须要加上命名空间名。
 
2、实体的别名:
  <typeAlias alias="Account" type="com.lavasoft.ibatissut.simple.domain.entity.Account"/>
  假设实用到的全名的地方。能够用别名取代,受命名空间约束。
 
3、插入操作
    对于自增主键的表,插入能够不配置插入的主键列。

否则是必须的。

 
4、获取主键
     插入语句之前配置:主要是针对Sequence主键而言,插入前必须指定一个主键值给要插入的记录。

Oracle、DB2亦如此。方法是在插入语句标签<insert....>之前配置上:

    <insert id="insertAccount" parameterClass="Account">

        <selectKey resultClass="long" keyProperty="sctId">

            SELECT SEQ_TEST.NEXTVAL FROM DUAL

        </selectKey>   
        insert into .... ........
    </insert>
  
    插入语句之后配置:蛀牙是针对自增主键的表而言,这类表在插入时不须要主键。而是在插入过程自己主动获取一个自增的主键。

比方MySQL

    <insert id="insertAccount" parameterClass="Account">

        <selectKey resultClass="long" keyProperty="sctId">

            SELECT LAST_INSERT_ID() 
       </selectKey>   
        insert into .... ........
    </insert>
 
   当然,是否须要配置<selectKey>依据情况。仅仅要能保证记录有主键就可以。一旦配置了<selectKey>,就能够在运行插入操作时获取到新增记录的主键。 
 
6、SQL入參parameterClass
  插入语句入參:parameterClass="类别名"  来设定。
  查询语句入參:能够设定类别名,也能够设定为map,也能够设定为iBatis支持的原生类型(比方string、int、long等)。当仅仅有一个原生类型入參时。则在SQL中用valuekeyword来引用。比方:
    <select id="getById"  parameterClass="long" resultMap="result_base">

        select * from customer where id = #value#

    </select>
    map是最强大的入參方式。不论什么入參方式都能够转换为这样的入參方式,由于iBatis仅接受一个入參,当几个參数分布在不同对象中的时候,将这些对象的属性(或者对象本身put)到map中,然后一次传递给sql语句是很有效。

能够自己写一个将对象或者对象集合转换为map的工具(我已经实现一个了)。

    另外。map的中的元素(比方pobj)是个复杂对象,则还能够在SQL中以#pobj.protyename#的格式来引用当中内嵌的属性。当然不推荐这么干。
 
7、返回值參数类型
      返回值參数也相同有两种类型,一种是对象类型resultClass="Account"。一种是resultMap="AccountResult"。

这两种类型的选择经常会令人迷惑不解,一言明其理:

当结果集列名和类属性名全然相应的时候,则应该使用resultClass来指定查询结果类型。当然有些列明不正确应。能够在sql中使用as重命名达到一致的效果。
 
当查询结果列名和类属性名相应不上的时候。应该选择resultMap指定查询结果集类型。

否则,则查询出来填充的对象属性为空(数字的为0。对象的为null)。

 
可是实际上resultMap是对一个Java Bean的映射。须要先定义xml的映射后。才干够引用。比如:
    <resultMap id="AccountResult" class="Account">

        <result property="id" column="ACC_ID"/>

        <result property="firstName" column="ACC_FIRST_NAME"/>

        <result property="lastName" column="ACC_LAST_NAME"/>

        <result property="emailAddress" column="ACC_EMAIL"/>

    </resultMap>
    resultMap映射的结果的目的就是要将查询的结果集绑定到映射对象的属性上。
 
   无论使用哪种返回值參数类型。其终于目的就是要把每条记录映射到一个类的对象或者对象集合上。假设有某个类属性映射不上。则在得到的这个对象或对象集合中这个属性为空。映射的属性能够是表与实体中的一部分。不要同一时候使用两种返回值參数类型。这样仅仅会令人迷惑。
 
8、查询结果集分组
    查询结果集排序有两种方式:一是在结果集映射上定义<resultMap id="result" class="bar" groupBy="id">。还有一种就是在SQL语句中分组。建议在SQL语句中分组,以获得更大的可控制性。

 
9、SQL中參数的引用
     SQL中引用parameterClass的參数有三种方式:
     iBatis内置支持的类型。比方int、string,使用#value#来引用。这个value是keyword,不可变。
     map类型的參数,使用#keyName#来引用,keyName为键名。
     复杂对象的參数,使用#propertyName#来引用。propertyName类属性的名字。
 
10、模糊查询中參数的引用
    模糊查询是针对字符串而言的,假设遇到两个单引號要包括一个參数。则不能再用#来引用变量了,而应该改为$,比方:'%$varName$%',当然,也能够使用 '%' || #varname# || '%' 来绕过此问题。

 
11、SQL片段
       能够通过<sql id="sql_xxx">...</sql>定义SQL片段。然后<include refid="sql_xxx"/>来在各种语句中引用。达到服用目的,
 
12、动态SQL
      能够通过使用动态SQL来组织灵活性更大的更通过的SQL,这样极大降低了编码量,是iBatis应用的第二大亮点。
     比方:一个动态的where条件
                <dynamic prepend="where">

                        <isNotEmpty prepend="and" property="$$$$$">

                                $name like '%'|| #$name# ||'%'

                        </isNotEmpty>

                        <isGreaterThan prepend="and" property="$$$$$" compareValue="$$$number">

                                $code like '%'|| #$code# ||'%'

                        </isGreaterThan>

                </dynamic>
     当然,prepend表示链接keyword,能够为不论什么字符串,当为sqlkeyword时,iBatis自己主动推断是否应该加入该keyword。

该语法也非常easy,关键是要会用心思考组织动态SQL。

    这里面有一点要注意:差别<isNotEmpty>和<isNotNull>差别,当为空空串时<isNotEmpty>返回true,当为空串时<isNotNull>返回真。哈哈。自己体会吧。说了反而啰嗦。
 
13、结果集映射继承
结果集映射的继承的目的是为了映射定义的复用,比方以下定义了两个映射。AccountResult继承了base:

    <resultMap id="base" class="Account">

        <result property="id" column="ACC_ID"/>

        <result property="firstName" column="ACC_FIRST_NAME"/>

        <result property="lastName" column="ACC_LAST_NAME"/>

    </resultMap>

    <resultMap id="AccountResult" class="Account" extends="Account.base">

        <result property="emailAddress" column="ACC_EMAIL"/>

    </resultMap>

这样,就非常easy扩展了一个映射策略。

       
14、查询注入
查询注入是在一个查询中嵌入另外一个查询,这样做的目的是为了实现实体对象之间的关联关联关系(一对一、一对多、多对多)分单项双向。有关这些内容,是比較复杂的,笔者对此做了深入研究,并分别写了三篇来讲述。
 
查询注入的实现就是在实体属性为另外一个实体或者实体集合的时候。引入一个相关的查询来实现。比如,客户和订单的映射关系:
public class Customer {

    private Long id;

    private String name;

    private String address;

    private String postcode;

    private String sex;

    private List<Orders> orderlist = new ArrayList<Orders>();
 
    <resultMap id="result" class="customer">

        <result property="id" column="id"/>

        <result property="name" column="name"/>

        <result property="address" column="address"/>

        <result property="postcode" column="postcode"/>

        <result property="sex" column="sex"/>

        <result property="orderlist" column="id" select="orders.findByCustomerId"/>

    </resultMap>
 
在这个映射中,为了查询客户的时候,能查询到相关的订单,能够在映射orderlist属性的时候,将其指向另外一个查询orders.findByCustomerId,这个查询是以Customer的id为參数来查询的。
 
select="orders.findByCustomerId"这个查询定义例如以下:
    <select id="findByCustomerId" resultMap="result_base" parameterClass="long">

        select * from orders where customerId = #value#

    </select>
 
原理就是这么简单,然后依据实际情况,能够自由实现实体间的关联关系。

 
14、iBatis的分页查询
iBatis的分页有两种方式。一点都不神奇,不要被网上的流言所迷惑。
第一种方式:结果集筛选分页。

先运行部分页的SQL查询语句,然后得到一个ResultSet。然后依据分页范围选择有效的记录填充到对象中。终于以集合的形式返回。

对于10w条一下的记录的表。不存在性能问题。假设存在,你能够选择第二中方式。

另外一种方式:SQL分页,通过组装分页类型的SQL来实现分页。这个关键在于分页參数的传递和分页SQL的构建。分页SQL构件每种数据库都不一样,不说了。分页參数的传递却能够通用。

我主张用map分装入參,连同分页參数一块传递进来,就搞定了。假设原来没有考虑到分页,而用的是对象做參数,则能够通过apache 的 beanutils组件来实现一个object到map之间的转换工具,问题迎刃而解。

 
当然。这还不是分页查询应用的最高境地。思考。分页须要计算一个总记录数,记录数运行的sql返回值是count(?),条件是除了分页以外的条件,因此应该将查询SQL静态分开,以MySQL为例,能够将查询分为查什么,和什么条件两部分,在条件部分对分页參数进行动态推断,假设分页參数就不分页,假设有则分页。这样最后仅仅须要两个组装的sql就能够计算总数和分页查询了。大大简化了问题的难度。

Oracle的解决思路也一样,不一样的地方就是拼装分页SQL改变了。

 
15、运行存储过程的配置
SQL Map 通过<procedure>元素支持存储过程。

以下的样例说明怎样使用具有输出參数

的存储过程。 

    <parameterMap id="swapParameters" class="map">

        <parameter property="email1" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>

        <parameter property="email2" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>

    </parameterMap>

    <procedure id="swapEmailAddresses" parameterMap="swapParameters">

        {call swap_email_address (?, ?)}

    </procedure> 

调用上面的存储过程将同一时候互换两个字段(数据库表)和參数对象(Map)中的两个 email地址。

假设參数的 mode 属性设为 INOUT 或 OUT,则參数对象的值被改动。否则保持不变。 

注意。要确保始终仅仅使用 JDBC 标准的存储过程语法。參考 JDBC 的 CallableStatement

文档以获得更具体的信息。

 
16、就是iBatis中各种id的命名了,这个看起来小菜一碟,可是搞砸了会非常痛苦。建议假设有DAO层的话。DAO接口的名字和SQL语句id的名字保持一致。同一时候,在DAO中将save和update封装为一个方法(从Hibernate中学来的),这是非常好的。也能够直接在SQL层将插入和更新柔和在一块,太复杂,有点影响效率。这见机行事了。

 
   另外Spring提供了各种数据操作模板。通过模板。擦做数据也就是“一句话”的问题,写个DAO还有必要么。尤其对iBatis来说,根本没有必要。

这样。就须要在领域活动层的设计上下功夫了。

 
17 、iBatis的查询也能够配置缓存策略,缓存的配置非常复杂,分非常多中情况,能够參看附件中的iBATIS-SqlMaps-2_cn.pdf的39页内容,有具体介绍。
 
18、偷懒的最高境地,让程序去干哪里80%的体力活。自己只把把关。不论什么反复的活动都有规律可循的。一旦发现了当中的规律,你就能够想办法把自己从中解脱出来。
    iBatis也不例外,每一个表都有增删改查、分页等操作。相应在每一个DAO方法上亦如此。

能够通过数据库生成sqlmap、entity、dao,然后将这些东西改吧改吧就完毕大部分的工作量。本人已经实现过了,当然开发这个工具的前提是你对iBatis有深入研究和理解。

 
-------------------------------------------------
以下是iBatis开发指南中内容:
 
附录:easy出错的地方 

本附录是译者加入的,列出了刚開始学习的人easy出错的地方。作为完毕高速入门课程后的学习

笔记,能够让刚開始学习的人少走些弯路。仅供參考。 

1)  在 parameterMap 和 resultMap 中。字段数据类型是 java.sql.Types 类定义的常量名

称。经常使用的数据类型包含 BLOB,CHAR,CLOB,DATE,LONGVARBINARY。 

INTEGER,NULL,NUMERIC,TIME,TIMESTAMP 和 VARCHAR 等。

2)  对于数据表中 NULLABLE 的字段,必须在 parameterMap 和 resultMap 中指定字段

的数据类型。 

3)  对于数据类型是 DATE,CLOB 或 BLOB 的字段。最好在 parameterMap 和 resultMap中指定数据类型。

4)  对于二进制类型的数据。能够将 LONGVARBINARY 映射成 byte[]。 

5)  对于文本类型较大的数据,能够将 CLOB 映射成 String。 

6) Java Bean 必须拥有缺省的构造器(即无參数的构造器)。

7) Java Bean 最好实现 Serializable 接口,以备应用的进一步扩展。

 
本人觉得:尽量避免在每一个入參后面附加參数的类型。以保持配置简洁。而且本人在长期开发中。没有发现必需要那么做。

iBatis2 SqlMap中经常使用sql语句的更多相关文章

  1. SQL Server中常用的SQL语句(转):

    SQL Server中常用的SQL语句 转自:http://www.cnblogs.com/rainman/archive/2013/05/04/3060428.html 1.概述 名词 笛卡尔积.主 ...

  2. 如何找出MySQL数据库中的低效SQL语句

    面对业务的迅猛发展,DBA的一项重要工作就是及时发现数据库中的低效SQL语句,有的可以立刻着手解决(比如缺少合适的索引),有的需要尽快反馈给开发人员进行修改. MySQL数据库有几个配置选项可以帮助我 ...

  3. SQL*PLUS中批量执行SQL语句

    SQL*PLUS中批量执行SQL语句 今天由于工作的需要,要在CMD中批量执行大量的SQL语句,对于Oracle学习还处在入门阶段的我,只能硬着头皮到处去寻找资料(主要是网络资料,也包括自己的电子书) ...

  4. 在ADO.NET中使用参数化SQL语句访问不同数据库时的差异

    在ADO.NET中经常需要跟各种数据库打交道,在不实用存储过程的情况下,使用参数化SQL语句一定程度上可以防止SQL注入,同时对一些较难赋值的字段(如在SQL Server中Image字段,在Orac ...

  5. SQL点滴32—Excel中CONCATENATE函数生成SQL语句

    原文:SQL点滴32-Excel中CONCATENATE函数生成SQL语句 当拿到一个Excel的时候需要将这里面的数据插入到数据库里面,该怎么办,除了使用SSIS数据导入之外还可以使用Excel中的 ...

  6. 在程序开发中怎样写SQL语句可以提高数据库的性能

    以下内容是公司dba总结. 1. 首先要搞明白什么叫执行计划?   执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来 ...

  7. Oracle数据库中,在SQL语句中连接字符串的方法是哪个?(选择1项)

    Oracle数据库中,在SQL语句中连接字符串的方法是哪个?(选择1项) A.cat B.concat C.join D.+ 解答:B

  8. 面试、笔试中常用的SQL语句(数据库知识必杀)一共50个!!!

    Student(S#,Sname,Sage,Ssex) 学生表  Course(C#,Cname,T#) 课程表  SC(S#,C#,score) 成绩表  Teacher(T#,Tname) 教师表 ...

  9. 【spring boot】【mybatis】spring boot中mybatis打印sql语句

    spring boot中mybatis打印sql语句,怎么打印出来?[参考:https://www.cnblogs.com/sxdcgaq8080/p/9100178.html] 在applicati ...

随机推荐

  1. 了解 Oracle Berkeley DB 可以为您的应用程序带来 NoSQL 优势的原因及方式。

    将 Oracle Berkeley DB 用作 NoSQL 数据存储 作者:Shashank Tiwari 2011 年 2 月发布 “NoSQL”是在开发人员.架构师甚至技术经理中新流行的一个词汇. ...

  2. boost 库的下载和编译_Visual Studio 2013(转)

    原文转自 http://blog.csdn.net/lp310018931/article/details/47791143 原文转自 http://m.blog.csdn.net/article/d ...

  3. php中Mail_mimeDecode无法读取foxmail等eml文件正文问题

    使用$cat -A xx.eml文件,发现foxmail的eml文件文件结尾和空行使用的\r\r\n, 如: Received: from WDGTO0MYSBX754J (unknown [106. ...

  4. mysql中文乱码的解决方法

    MySQL的字符集支持(Character Set Support)有两个方面: 字符集(Character set)和排序方式(Collation).对于字符集的支持细化到四个层次: 服务器(ser ...

  5. AC日记——[SCOI2007]蜥蜴 bzoj 1066

    1066 思路: 网络流最大流: 拆点,每个点拆成两个,流量为这个点的高度: 注意,文中说的距离是曼哈顿距离(劳资以为开根号wa了不知道多少次): 每两个距离不大于d的点连边,流量inf: 如果距离能 ...

  6. JS中 this 的四种用法

    1.在一般函数中使用 this 指全局对象 window function fn(){ this.x = 1 } fn(); //相当于window.fn() 2.作为对象方法使用 this 指该对象 ...

  7. Network| ICMP

    Internet Control Message Protocol,ICMP是网路协议族的核心协议之一.它用于TCP/IP网络中发送控制消息,提供可能发生在通信环境中的各种问题反馈,通过这些信息,令管 ...

  8. Windows Server 2008 IE 无法调整安全级别

    开始”/“程序”/“管理工具”/“服务器管理器”命令,在弹出的服务器管理器窗口中,找到“安全信息”设置项,单击其中的“配置IE ESC”选项,打开如下图所示的IE增强安全配置窗口.

  9. mysql之select,insert,delete,update

    写在前面 上篇文章学习了创建数据库和数据表,这篇文章将学习对数据表的增删改查操作. 系列文章 mysql之创建数据库,创建数据表 一个例子 上篇文章中,创建了数据库和数据表,数据表中还没有数据,这里我 ...

  10. ios内存管理笔记(三)

    我们在进行iOS开发时,经常会在类的声明部分看见类似于@synthesize window=_window; 的语句,那么,这个window是什么,_ window又是什么,两个东西分别怎么用,这是一 ...