iBatis2之SqlMap配置总结(18条)

iBatis2之SqlMap配置总结(18条)  

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中用value关键字来引用。比如:

<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是关键字,不可变。

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表示链接关键字,可以为任何字符串,当为sql关键字时,iBatis自动判断是否应该添加该关键字。该语法也很简单,关键是要会用心思考组织动态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>

这样,就很容易扩展了一个映射策略。

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的查询也可以配置缓存策略,缓存的配置很复杂,分很多中情况,要获得详细的信息,请参考 OSCache 文档。OSCache 及其文档可以从 OpenSymphony
网站上获取:
http://www.opensymphony.com/oscache/

18、偷懒的最高境界,让程序去干哪里80%的体力活。自己仅仅把把关。任何重复的活动都有规律可循的,一旦发现了其中的规律,你就可以想办法把自己从中解脱出来。

iBatis也不例外,每个表都有增删改查、分页等操作。对应在每个DAO方法上亦如此。可以通过数据库生成sqlmap、entity、dao,然后将这些东西改吧改吧就完成大部分的工作量。当然开发这个工具的前提是你对iBatis有深入研究和理解。

-------------------------------------------------

下面是iBatis开发指南中内容:

附录:容易出错的地方
本附录是译者添加的,列出了初学者容易出错的地方,作为完成快速入门课程后的学习 笔记,可以让初学者少走些弯路。

仅供参考。

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配置总结(18条)

时间: 2024-12-24 07:23:58

iBatis2之SqlMap配置总结(18条)的相关文章

独立开发者低成本推广APP的18条技巧

导语:知道并不等于执行,有些最基本的推广方法往往会被忽略.这些,是自国外开发者总结出的这18条经验. 现在市面上充满了大牌子大公司和大制作的手机游戏,经常有游戏花300万成本开发,然后再花2000万推广;这些游戏都梦想着上线之后就有4000万月流水疯狂吸金.但是作为独立开发者,就算没有多少推广的费用,也有很多推广的策略和方法能让你不花钱就获得效果.这些技巧和方法并不是什么奇妙高招,或多或少开发者你都会知道,但是知道并不等于执行,有些最基本的推广方法也往往会被忽略.我们将来自国外开发者总结出的这1

13年棘手Bug调试总结18条教训(值得收藏)

曾经在<Learning From Your Bugs(从你的错误中学习)>一文中,我写了关于我是如何追踪我所遇到的一些最有趣的bug.最近,我回顾了我所有的194个条目(从13岁开始),看看有什么经验教训是我可以学习的.下面是我总结的最重要的经验教训,包括编码,测试和调试三个方面. 编码 下面这些都是我经历过的会导致难点bug的问题: 1.事件顺序.在处理事件时,提出下列问题会很有成效:事件可以以不同的顺序到达吗?如果我们没有接收到此事件会怎么样?如果此事件接连发生两次会怎么样?哪怕通常不会

iptables配置顺序-两条规则会忽略后边的

oracle在centos本机能够正常访问,关闭防火墙也能够远程访问,但是一旦开启防火墙则不能远程访问 尝试添加规则iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 1521 -j ACCEPT,但是仍然不能远程访问 尝试vi /etc/sysconfig/iptables,修改配置添加-A INPUT -m state --state NEW -m tcp -p tcp --dport 1521 -j ACCEPT,保存返

第18条:接口优先抽象类

Java程序设计语言提供了两种机制,可以用来定义允许多个实现的类型:接口和抽象类.这两种机制之间最明显的区别在于: 1.抽象类允许包含某些方法的实现,但是接口不允许 2.为了实现由抽象类定义的类型,类必须为抽象类的一个子类 任何一个类,只要它定义了所有必要的方法,并且遵守通用约定,它就被允许实现一个接口,而不管这个类是处于类层次(class hierarchy)的哪个位置.因为Java是单继承的,所以抽象类作为类型定义受到了极大的限制. 现有的类可以很容易被更新,以实现新的接口.如果这些方法尚不

18条效率至少提高3倍的MySQL技巧

1.EXPLAIN 做MySQL优化,我们要善用EXPLAIN查看SQL执行计划. type列,连接类型.一个好的SQL语句至少要达到range级别.杜绝出现all级别. key列,使用到的索引名.如果没有选择索引,值是NULL.可以采取强制索引方式. key_len列,索引长度. rows列,扫描行数.该值是个预估值. extra列,详细说明.注意,常见的不太友好的值,如下:Using filesort,Using temporary 2.SQL语句中IN包含的值不应过多 MySQL对于IN做

汇课新知-想要在网上打工赚钱?必须要知道的18条网赚思维

超过90%的在线收入和兼职工作都在徘徊和困惑.如果你在做任何事情之前理解了思考的逻辑,你将能够以有序的方式前进. 在互联网上分享18种赚钱方式: 1.有些项目我们绝对不碰,不喜欢那种资金托盘.我们认识我们身边的许多兄弟,因为他们从事基金托盘业务.最后,它们是空的.赚两亿美元怎么样?他们失去了生命,什么也不做.所以我们一直没有接触过灰色和黑色的项目.这不是我们的胆量,而是我们想稳妥.安全地做事.毕竟,许多兄弟都有家庭.妻子和孩子,稳定地赚钱就足够了. 2.每天锻炼可以改善你的健康.每天读书会使你受

第18条:尽量使用不可变对象

1.设计类的时候,应充分运用属性来封装数据. 2.应该尽量把对外公布出来的属性设为只读,而且只在确有必要时才将属性对外公布. 3.若属性仅可于对象内部修改,则在“class-continuation分类”中将其由readonly属性扩展为readwrite属性. 这种做法下,如果该属性是nonatomic,那么可能会产生“竞争条件”(race condition, 竞态条件).在对象内部写入属性时,对象外的观察者也许正读取该属性.若想避免此问题,可以在必要时通过“派发队列”(dispatch q

学好英语的18条黄金法则

1.What is language for? Some people seem to think it is for practicing grammar or learning lists of words—the longer the words the better. That's wrong.Language is for the exchange of ideas, for communication. 2.The way to learn a language is to prac

网站搜索引擎优化(SEO)的18条守则

1.永远不要放过网页的title,这个地方应该是你每次优化的重点. 2.请不要在title,deion,keyword里写太多东西,越是贪婪,得到的就越少. 3.网页的头部和底部是很重要的,对于搜索引擎来说,尽量的将关键字加到里面. 4.关键字需要认真选择,不要选的太宽,太宽你做不赢门户,也不要选的太窄,太窄就算做到第一了,也没多少流量. 5.做SEO至少要有点东西护体,就算你做垃圾站,至少在视觉上像个正规站,不要一进去就内衣,性用品广告满天飞,就算不被K,用户也会鄙视 你. 6.不要去在乎所谓