• ibatis动态查询


    在复杂查询过程中,我们常常需要根据用户的选择决定查询条件,这里发生变化的
    并不只是SQL 中的参数,包括Select 语句中所包括的字段和限定条件,都可能发生变
    化。典型情况,如在一个复杂的组合查询页面,我们必须根据用户的选择和输入决定查
    询的条件组合。
    一个典型的页面如下:
    对于这个组合查询页面,根据用户选择填写的内容,我们应为其生成不同的查询语
    句。
    如用户没有填写任何信息即提交查询请求,我们应该返回所有记录:
    Select * from t_user;
    如用户只在页面上填写了姓名“Erica”,我们应该生成类似:
    Select * from t_user where name like ‘%Erica%’ ;
    的SQL查询语句。
    如用户只在页面上填写了地址“Beijing”,我们应该生成类似:
    Select * from t_user where address like ‘%Beijing%”;
    的SQL。
    而如果用户同时填写了姓名和地址(”Erica”&’Beijing’),则我们应生成类似:
    Select * from t_user where name like ‘%Erica%’ and address like ‘%Beijing%”
    的SQL查询语句。
    对于ibatis 这样需要预先指定SQL 语句的ORM 实现而言,传统的做法无非通过
    if-else 语句对输入参数加以判定,然后针对用户选择调用不同的statement 定义。对于
    上面这种简单的情况(两种查询条件的排列组合,共4 种情况)而言,statement 的重
    复定义工作已经让人不厌其烦,而对于动辄拥有七八个查询条件,乃至十几个查询条件
    的排列组合而言,琐碎反复的statement定义实在让人不堪承受。
    考虑到这个问题,ibatis引入了动态映射机制,即在statement定义中,根据不同的
    查询参数,设定对应的SQL语句。
    还是以上面的示例为例:
    <select id="getUsers"
    parameterClass="user"
    resultMap="get-user-result">
    select
    id,
    name,
    sex
    from t_user
    <dynamic prepend="WHERE">
    <isNotEmpty prepend="AND" property="name">
    (name like #name#)
    </isNotEmpty>
    <isNotEmpty prepend="AND" property="address">
    (address like #address#)
    </isNotEmpty>
    </dynamic>
    </select>
    通过dynamic 节点,我们定义了一个动态的WHERE 子句。此WHERE 子句中将
    可能包含两个针对name 和address 字段的判断条件。而这两个字段是否加入检索取决
    于用户所提供的查询条件(字段是否为空[isNotEmpty])。
    对于一个典型的Web程序而言,我们通过HttpServletRequest获得表单中的字段名
    并将其设入查询参数,如:
    user.setName(request.getParameter("name"));
    user.setAddress(request.getParameter("address"));
    sqlMap.queryForList("User.getUsers", user);
    在执行queryForList("User.getUsers", user)时,ibatis 即根据配置文
    件中设定的SQL动态生成规则,创建相应的SQL语句。
    上面的示例中,我们通过判定节点isNotEmpty,指定了关于name 和address 属
    性的动态规则:
    <isNotEmpty prepend="AND" property="name">
    (name like #name#)
    </isNotEmpty>
    这个节点对应的语义是,如果参数类的"name"属性非空(isNotEmpty,即非空
    字符串””),则在生成的SQL Where字句中包括判定条件(name like #name#),其
    中#name#将以参数类的name属性值填充。
    Address属性的判定生成与name属性完全相同,这里就不再赘述。
    这样,我们通过在statement 定义中引入dynamic 节点,很简单的实现了SQL 判
    定子句的动态生成,对于复杂的组合查询而言,这将带来极大的便利。
    判定节点的定义可以非常灵活,我们甚至可以使用嵌套的判定节点来实现复杂的动
    态映射,如:
    <isNotEmpty prepend="AND" property="name">
    ( name=#name#
    <isNotEmpty prepend="AND" property="address">
    address=#address#
    </isNotEmpty>
    )
    </isNotEmpty>
    这段定义规定,只有用户提供了姓名信息时,才能结合地址数据进行查询(如果只
    提供地址数据,而将姓名信息忽略,将依然被视为全检索)。
    Dynamic节点和判定节点中的prepend属性,指明了本节点中定义的SQL子句在
    主体SQL中出现时的前缀。
    如:
    <dynamic prepend="WHERE">
    <isNotEmpty prepend="AND" property="name">
    (name like #name#)
    </isNotEmpty>
    <isNotEmpty prepend="AND" property="address">
    (address like #address#)
    </isNotEmpty>
    </dynamic>
    假设"name"属性的值为“Erica”, "address"属性的值为“Beijing”,则会
    生成类似下面的SQL子句(实际运行期将生成带占位符的PreparedStatement,之
    后再为其填充数据):
    WHERE (name like ‘Beijing’) AND (address like ‘Beijing’)
    其中WHERE 之后的语句是在dynamic 节点中所定义,因此以dynamic 节点的
    prepend设置("WHERE")作为前缀,而其中的”AND”,实际上是address属性所对
    应的isNotEmpty节点的prepend设定,它引领了对应节点中定义的SQL子句。至于
    name属性对应的isNotEmpty节点,由于ibatis会自动判定是否需要追加prepend
    前缀,这里(name like #name#)是WHERE 子句中的第一个条件子句,无需AND 前
    缀,所以自动省略。
    判定节点并非仅限于isNotEmpty,ibatis中提供了丰富的判定定义功能。
    判定节点分两类:
    ? 一元判定
    一元判定是针对属性值本身的判定,如属性是否为NULL,是否为空值等。
    上面示例中isNotEmpty就是典型的一元判定。
    一元判定节点有:
    节点名 描述
    <isPropertyAvailable> 参数类中是否提供了此属性
    <isNotPropertyAvailable> 与<isPropertyAvailable>相反
    <isNull> 属性值是否为NULL
    <isNotNull> 与<isNull>相反
    <isEmpty> 如果属性为Collection或者String,其size是否<1,
    如果非以上两种类型,则通过
    String.valueOf(属性值)
    获得其String类型的值后,判断其size是否<1
    <isNotEmpty> 与<isEmpty>相反。
    ? 二元判定
    二元判定有两个判定参数,一是属性名,而是判定值,如
    <isGreaterThan prepend="AND" property="age"
    compareValue="18">
    (age=#age#)
    </isGreaterThan>
    其中,property="age"指定了属性名”age”,compareValue=”18”指明
    了判定值为”18”。
    上面判定节点isGreaterThan 对应的语义是:如果age 属性大于
    18(compareValue),则在SQL中加入(age=#age#)条件。
    二元判定节点有:
    节点名 属性值与compareValues的关系
    <isEqual> 相等。
    <isNotEqual> 不等。
    <isGreaterThan> 大于
    <isGreaterEqual> 大于等于
    <isLessThan> 小于
    <isLessEqual> 小于等于

  • 相关阅读:
    宽度高度sizeWithFont:constrainedToSize:lineBreakMode的使用
    端口错误安卓模拟器不能启动:The connection to adb is down, and a severe error has occurred的解决办法
    树磁盘[HBase] LSM树 VS B+树
    请求方法Jsp&servlet面试题
    数组最小(百度面试题目)对升序数组,求数组中绝对值最小的元素
    类代理java设计模式动态代理(简单笔记)
    数据插入difference between count(*) and count(col) in the query
    跟踪查看oracle 执行计划获取的几种方式
    类型字节oracle 增强型时间类型以及postgresql时间类型
    类方法[笔记]Java基础加强(57天)2010年Java高新技术_张孝祥
  • 原文地址:https://www.cnblogs.com/wcyBlog/p/3881299.html
Copyright © 2020-2023  润新知