映射文件总体形式:
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
resultMap=”productResult” cacheModel=”product-cache”>
select * from PRODUCT where PRD_ID = ?
映射的查询语句形式:
[parameterClass=”some.class.Name”]
[resultClass=”some.class.Name”]
[parameterMap=”nameOfParameterMap”]
[resultMap=”nameOfResultMap”]
[cacheModel=”nameOfCache”]
[timeout=“5”]>
select * from PRODUCT where PRD_ID = [?|#propertyName#]
order by [$simpleDynamic$]
insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (1, “Shih Tzu”)
SELECT *
FROM PERSON
WHERE AGE > ]]> #value#
下面的表格说明了所有支持的查询语句形式及其属性:
可定义SQL Fragments对部分SQL语句进行复用:
FROM items
WHERE parentid = 6
SELECT COUNT(*) AS total
SELECT id, name
对某些数据库的自动增长键有支持,但不同的支持策略,例:
SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL
insert into PRODUCT (PRD_ID,PRD_DESCRIPTION)
values (#id#,#description#)
insert into PRODUCT (PRD_DESCRIPTION)
values (#description#)
SELECT @@IDENTITY AS ID
更具体内容参见帮助文档。
存储过程:
{call swap_email_address (?, ?)}
存储过程影响数据库表,同时也影响参数对象,mode若是INOUT或OUT,参数对象会被改变,否则不改变。
对于映射查询,iBatis建议:参数使用inline-parameter,也就是parameterClass(不是parameterMap),而结果使用resultMap(不是resultClass)。
parameterMap格式:
[nullValue=“-9999”] [typeName=”{REF or user-defined type}”] [resultMap=someResultMap] [mode=IN|OUT|INOUT] [typeHandler=someTypeHandler] [numericScale=2]/> resultMap格式: [extends=”parent-resultMap”] [groupBy=“some property list”]> [columnIndex=”1”] [javaType=”int”] [jdbcType=”NUMERIC”] [nullValue=”-999999”] [select=”someOtherStatement”] [resultMap=“someOtherResultMap”] [typeHandler=“com.mydomain.MyTypehandler”] /> java.util.Map接口的实现类也可作为parameterMap或resultMap的class。 复杂查询: N+1查询(结合cache的话会比连接查询好,没有cache很糟): select * from PRODUCT where PRD_ID = #value# select * from CATEGORY where CAT_ID = #value# 连接查询(iBatis解决复杂查询的通常方式,但有cache时候可能不如N+1查询): select * from PRODUCT, CATEGORY where PRD_CAT_ID=CAT_ID and PRD_ID = #value# 或者: select * from PRODUCT, CATEGORY where PRD_CAT_ID=CAT_ID and PRD_ID = #value# 复杂集合查询: N+1法: select * from CATEGORY where CAT_ID = #value# select * from PRODUCT where PRD_CAT_ID = #value# groupBy法: select C.CAT_ID, C.CAT_DESCRIPTION, P.PRD_ID, P.PRD_DESCRIPTION from CATEGORY C left outer join PRODUCT P on C.CAT_ID = P.PRD_CAT_ID where CAT_ID = #value# 注:groupBy属性不能和queryForPaginatedList()调用同时使用。 N+1查询中的符合查询: … select=”getOrderPayments”/> select * from PAYMENT where PAY_ORD_ID = #itemId# and PAY_CST_ID = #custId# 数据类型表: 自定义TypeHandler: public class YesNoBoolTypeHandlerCallback implements TypeHandlerCallback { private static final String YES = "Y"; private static final String NO = "N"; public Object getResult(ResultGetter getter) throws SQLException { String s = getter.getString(); if (YES.equalsIgnoreCase(s)) { return new Boolean (true); } else if (NO.equalsIgnoreCase(s)) { return new Boolean (false); } else { throw new SQLException ( "Unexpected value " + s + " found where " + YES + " or " + NO + " was expected."); } } public void setParameter(ParameterSetter setter, Object parameter) throws SQLException { boolean b = ((Boolean)parameter).booleanValue(); if (b) { setter.setString(YES); } else { setter.setString(NO); } } public Object valueOf(String s) { if (YES.equalsIgnoreCase(s)) { return new Boolean (true); } else { return new Boolean (false); } } 然后在sqlMapConfig文件里加上如下配置: javaType="boolean" jdbcType=”VARCHAR” callback="org.apache.ibatis.sqlmap.extensions.YesNoBoolTypeHandlerCallback"/> 缓存设置: select * from PRODUCT where PRD_CAT_ID = #value# Readonly属性默认为true,但若想要在返回的对象上做更改的话,设为false。 Serialize属性设置为false后,该cache为全局共享cache,这种cache不能是readOnly的(因为没意义)。 Cache的种类: MEMORY——java特殊引用类实现的cache 所有的referencetype: LRU——最少使用算法的cache: FIFO——先进先出算法的cache: OSCACHE——插件cache,opensymphony的cache实现,参见:http://www.opensymphony.com/oscache/ 构造动态SQL语句: prepend – 加在本体前面的预设字符 (可选) open – 标识本体开始的开始字符串(可选) close – 标识本题结束的结束字符串 (可选) dynamic元素的removeFirstPrepend属性是强制的,所以它的第一个子元素的prepend字符串在生成语句的时候总是会被取消掉。 二元操作标记: 属性: prepend – the overridable SQL part that will be prepended to the statement (optional) property – the property to be compared (required) compareProperty – the other property to be compared (required or compareValue) compareValue – the value to be compared (required or compareProperty) removeFirstPrepend – removes the prepend of the first nested content producing tag (true|false, optional) open – the string with which to open the entire resulting body content (optional) close – the string with which to close the entire resulting body content (optional) 举例: ADOLESCENT = ‘TRUE’ 一元判断标记: is null or empty (“” or size() < 1). is not null and not empty (“” or size() < 1). 属性: prepend – the overridable SQL part that will be prepended to the statement (optional) property – the property to be checked (required) removeFirstPrepend – removes the prepend of the first nested content producing tag (true|false, optional) open – the string with which to open the entire resulting body content (optional) close – the string with which to close the entire resulting body content (optional) 举例: FIRST_NAME=#firstName# 其它标记: 属性: prepend – the overridable SQL part that will be prepended to the statement (optional) removeFirstPrepend – removes the prepend of the first nested content producing tag (true|false, optional) open – the string with which to open the entire resulting body content (optional) close – the string with which to close the entire resulting body content (optional) 举例: EMPLOYEE_TYPE = ‘DEFAULT’ java.util.Iterator, or is an array. 例: open=”(” close=”)” conjunction=”OR”> username=#userNameList[]# 当集合类单独被当作参数传进此查询时,也可以这么写: username=#[]# 也可以像这样选择集合中对象的属性: open=”(” close=”)” conjunction=”OR”> firstname=#userList[].firstName# and lastname=#userList[].lastName# 该标签还可以自己嵌套: ( conjunction="and"> $orConditions[].conditions[].condition$ #orConditions[].conditions[].value# ) 若只是想生成一些简单的动态sql语句,这样写就可以: select * from PRODUCT order by $preferredOrder$ 注意“$”,不是“#”,这是和为preparedStatement赋值的普通属性的取得的不同之处。