zoukankan      html  css  js  c++  java
  • 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> 小于等于

  • 相关阅读:
    [kuangbin带你飞]专题十六 KMP & 扩展KMP & ManacherK
    [kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher J
    [kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher I
    pat 1065 A+B and C (64bit)(20 分)(大数, Java)
    pat 1069 The Black Hole of Numbers(20 分)
    pat 1077 Kuchiguse(20 分) (字典树)
    pat 1084 Broken Keyboard(20 分)
    pat 1092 To Buy or Not to Buy(20 分)
    pat 1046 Shortest Distance(20 分) (线段树)
    pat 1042 Shuffling Machine(20 分)
  • 原文地址:https://www.cnblogs.com/wcyBlog/p/3881299.html
Copyright © 2011-2022 走看看