用IBATIS做一个多关键词查询的功能,
用户可以输入任意多个关键词,比如K1,K2,K3...
也可以是一个。
那么在写WHERE子句的时候应该根据关键词的数量写,
如下:
where text like '%'||#K1#||'%' and text like '%'||#K2#||'%' and text like '%'||#K3#||'%' .....
因为关键词的数量并不是固定的。
所以IBATIS里需要拼接这个WHERE子句,那么该如何写呢?

解决方案 »

  1.   

    IBATIS貌似只支持传入一个参数 多个参数的话把它分装成一个类 然后传入这个类的实例就行 要是参数个数不确定的话 还是JDBC吧。。
      

  2.   

    定义一个和Form一样的对象类
    .XML如下:
    SELECT。
    <dynamic prepend="WHERE"> 
        <isNotEmpty prepend="AND" property="name"> 
        NAME  like #name# 
        </isNotEmpty>
        <isNotEmpty prepend="AND" property="phone"> 
        FILE_NAME like #file_name# 
        </isNotEmpty>
    .....
    ......有多少+多少,动态的
    </dynamic> 
      

  3.   

    一元判定
    一元判定是针对属性值本身的判定,如属性是否为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> 小于等于
      

  4.   

    用动态SQL.LZ可以试试iBator自动生成的SQLMAP
      

  5.   

    ibatis 有动态生成 sql的功能,就像楼2楼提供思路一样
      

  6.   

    lz是的是不是这个? <iterate property="keywords" conjunction="AND">
       p.propertyCN LIKE '%$keywords[]$%'
    </iterate>
    这个就是把所有keywords里面的东西,传接成一个sql
    其中keywords是一个从parameter里面传进来的list对象
    结果是
    p.propertyCN LIKE '%123%' AND p.propertyCN LIKE '%abc%' good luck
      

  7.   


    多谢,我的意思正是这个。我用你的方法去测试了,
    一直报错,
    2009-08-17 17:47:46,828 ERROR [com.alt.rgs.search.action.SearchForKeywordAction]
     -
    --- The error occurred in com/alt/rgs/bean/SearchResultBean.xml.
    --- The error occurred while preparing the mapped statement for execution.
    --- Check the getText4.
    --- Check the parameter map.
    --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list fr
    om JavaBean. Cause java.lang.NumberFormatException: For input string: ""
    我2个小时换了各种方式各种写法,一直报这个错误,
    不知道你以前有没有遇到过,会不会是IBATIS的BUG呢?
    我的版本是IBATIS2.3.0
      

  8.   

    我的SQL:select file_id,file_pos,file_data
         from rgs_text where
         <iterate property="keywords" conjunction="AND">
                      file_data LIKE #keywords[]#
                </iterate>[
    select file_id,file_pos,file_data
         from rgs_text where
         <iterate property="keywords" conjunction="AND">
                      file_data LIKE '%$keywords[]$%'
    这些我都用过,都抱一样的错,
      

  9.   

    加分了,请villagehead兄帮忙解答,
    分不够再加。
    多谢了
      

  10.   

    错误提示显示你的""转化成数字的时候发生错误,
    这是类型转化错误,你的两种方式都是正确的,所以请检查file_data和keywords的类型是否正确
      

  11.   


    SQL> desc rgs_text;
    Name       Type           Nullable Default Comments 
    ---------- -------------- -------- ------- -------- 
    FILE_ID    VARCHAR2(50)   Y                         
    FILE_POS   INTEGER        Y                         
    FILE_DATA  VARCHAR2(4000) Y                         
    FILE_FLAG  INTEGER        Y        0                
    FILE_STYLE INTEGER        Y        0    map.put("keywords", keywords); 
    keywords是一个List,这些都是没问题的           
      

  12.   

    java.lang.NumberFormatException: For input string: "" Landor2004是根据这句觉得我的file_data和keywords的类型可能有问题吧,
    其实我到觉得For input string: "" 当中的""应该指的是file_data LIKE '%$keywords[]$%'种[]中的"",
    如果我把file_data LIKE '%$keywords[]$%'改为file_data LIKE '%$keywords[0]$%',
    那么不报这个错,而报missing expression,缺失表达式错误。
      

  13.   

    你好,你这个错误我也没有遇到过,
    或者是开发的时候遇到过也不记得了。这类的错误,基本上是你运行期的时候,有什么不合法的数据传进去了导致的。你检查一下你传进去的list里面的值吧。另外,你的parameterClass指定的是map吗?ProbeException一般都是说你传进去的参数里没有相应属性的getter方法还有,也有可能因为你的FILE_POS字段是数字,
    但是又可以为null,
    在ibatis取得null值的时候,不能把一个空传给一个bean的属性,
    也没准是这个问题。如果是这个问题的话,2个解决办法。
    1、resultMap里面加上类似defaultValue的东西,具体属性名不记得了。lz自己查查
    2、在sql里面动手脚,用类似decode的东西转换一下
    在bean里面的setter设置一下也行应该,不过没试过。
    要还不行你把select标签里的完整内容

    你调用的时候的代码
    都贴上来看看?good luck
      

  14.   

    建议LZ检查下sqlmap,比如字段名是否对应,类型是否对应
      

  15.   


    多谢villagehead兄的关注,
    很抱歉这两天由于换机器等一些杂事,一直忙不过来,现在才能给你回复。
    <select id="getText4" parameterClass="java.util.Map"  resultClass="java.lang.Integer">
    <![CDATA[ 
    select count(*) from rgs_itemdata where id in 
    <iterate open="(" close=")" conjunction=",">
    #test[0]#
    </iterate>
    <!--
        select file_id,file_pos,file_data
         from rgs_text where
         <iterate property="keywords" conjunction="AND">
                      file_data LIKE #keywords[]#
                </iterate>
                -->
        
          ]]>以前的都被我注释掉了,现在用最简单的SQL来测试,还是报一样的错误。
    --- Check the parameter map.
    --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list fr
    om JavaBean. Cause java.lang.NumberFormatException: For input string: ""SQL> desc rgs_itemdata;
    Name           Type          Nullable Default Comments 
    -------------- ------------- -------- ------- -------- 
    ID             VARCHAR2(6)   Y                         
    FILE_ID        VARCHAR2(255) Y                         
    FILE_POS       VARCHAR2(255) Y                         
    FILE_NAME      VARCHAR2(255) Y                         
    FILE_TIME      VARCHAR2(255) Y                         
    FILE_FIXDATA   VARCHAR2(255) Y                         
    FILE_WORDPATH  VARCHAR2(255) Y                         
    FILE_SENDTYPE  VARCHAR2(255) Y                         
    FILE_SENDUNITS VARCHAR2(255) Y                         
    FILE_EFFECT    VARCHAR2(255) Y                         
    FILE_STATE     VARCHAR2(255) Y                         
    FILE_UPPATH    VARCHAR2(255) Y                         
    FILE_VERSION   INTEGER       Y                         
    FILE_SHARE     VARCHAR2(5)   Y                         
     public List<SearchResultBean> queryForText(List keywords) throws SQLException{
    Map map = new HashMap();
    List aList = new ArrayList<Integer>();
    aList.add(1);
    aList.add(2);
    map.put("keywords", keywords);
    map.put("test", aList);
    this.getSqlMapClient().queryForList("getText4", map);
    return textList;
    }
      

  16.   

     -
    --- The error occurred in com/alt/rgs/bean/SearchResultBean.xml.
    --- The error occurred while preparing the mapped statement for execution.
    --- Check the getText4.
    --- Check the parameter map.
    --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list fr
    om JavaBean. Cause java.lang.NumberFormatException: For input string: ""
    com.ibatis.common.jdbc.exception.NestedSQLException:这是比较完整的LOG信息。
      

  17.   

    你返回integer的,就不能用queryForList了
    要用queryForObject另外,你的    this.getSqlMapClient().queryForList("getText4", map);
        return textList;是不是为了测试才这个样子的?
    textList没赋值啊good luck
      

  18.   

    呵呵,多谢,我是为了测试才这样写的,
    改成queryForObject 还是报一样的错
      

  19.   

    #test[0]#
    应该是
    #test[]#另外,把你的log打印出来看看,
    看sql是不是正确log4j的配置方法是:
    log4j.logger.com.ibatis=debug
    log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug
    log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug
    log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug
    log4j.logger.java.sql.Connection=debug
    log4j.logger.java.sql.Statement=debug
    log4j.logger.java.sql.PreparedStatement=console, debuggood luck
      

  20.   

    还不行把
    #test[]# 
    换成
    $test[]$
    再试试 good luck
      

  21.   

    #test[0]#和
    #test[]# 两种我都尝试了,
    可能刚刚发帖的时候正好写的是#test[0]#
    我把完整的日志发上来,不过也没什么特别的提示,愁啊
    2009-08-20 11:51:44,843 ERROR [com.alt.rgs.search.action.SearchForKeywordAction]
     -
    --- The error occurred in com/alt/rgs/bean/SearchResultBean.xml.
    --- The error occurred while preparing the mapped statement for execution.
    --- Check the getText4.
    --- Check the parameter map.
    --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list fr
    om JavaBean. Cause java.lang.NumberFormatException: For input string: ""
    com.ibatis.common.jdbc.exception.NestedSQLException:
    --- The error occurred in com/alt/rgs/bean/SearchResultBean.xml.
    --- The error occurred while preparing the mapped statement for execution.
    --- Check the getText4.
    --- Check the parameter map.
    --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list fr
    om JavaBean. Cause java.lang.NumberFormatException: For input string: ""
            at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQue
    ryWithCallback(MappedStatement.java:204)
            at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQue
    ryForList(MappedStatement.java:139)
            at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(Sql
    MapExecutorDelegate.java:567)
            at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(Sql
    MapExecutorDelegate.java:541)
            at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSe
    ssionImpl.java:118)
            at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForList(SqlMapCli
    entImpl.java:94)
            at com.alt.rgs.search.dao.SearchForKeywordDao.queryForText(SearchForKeyw
    ordDao.java:30)
            at com.alt.rgs.search.service.SearchForKeywordService.SearchTextForKeywo
    rd(SearchForKeywordService.java:51)
            at com.alt.rgs.search.action.SearchForKeywordAction.doPost(SearchForKeyw
    ordAction.java:55)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl
    icationFilterChain.java:290)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF
    ilterChain.java:206)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperV
    alve.java:233)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextV
    alve.java:191)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.j
    ava:128)
            at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.j
    ava:102)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineVal
    ve.java:109)
            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.jav
    a:286)
            at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java
    :845)
            at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.proce
    ss(Http11Protocol.java:583)
            at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:44
    7)
            at java.lang.Thread.run(Thread.java:619)
    Caused by: com.ibatis.common.beans.ProbeException: Error getting ordinal list fr
    om JavaBean. Cause java.lang.NumberFormatException: For input string: ""
            at com.ibatis.common.beans.BaseProbe.getIndexedProperty(BaseProbe.java:8
    6)
            at com.ibatis.common.beans.ComplexBeanProbe.getProperty(ComplexBeanProbe
    .java:297)
            at com.ibatis.common.beans.ComplexBeanProbe.getObject(ComplexBeanProbe.j
    ava:198)
            at com.ibatis.common.beans.GenericProbe.getObject(GenericProbe.java:74)
            at com.ibatis.sqlmap.engine.exchange.ComplexDataExchange.getData(Complex
    DataExchange.java:65)
            at com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap.getParameterO
    bjectValues(ParameterMap.java:133)
            at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQue
    ryWithCallback(MappedStatement.java:181)
            ... 22 more
    Caused by: java.lang.NumberFormatException: For input string: ""
            at java.lang.NumberFormatException.forInputString(NumberFormatException.
    java:48)
            at java.lang.Integer.parseInt(Integer.java:470)
            at java.lang.Integer.parseInt(Integer.java:499)
            at com.ibatis.common.beans.BaseProbe.getIndexedProperty(BaseProbe.java:5
    1)
            ... 28 more
      

  22.   

    辛苦villagehead兄了,
    改了还是报一样的错误,
    <select id="getText4" parameterClass="java.util.Map"  resultClass="java.lang.Integer">
    <![CDATA[ 
    select count(*) from rgs_itemdata where id in 
    <iterate property="test" open="(" close=")" conjunction=",">
    $test[]$
    </iterate>
    <!--
        select file_id,file_pos,file_data
         from rgs_text where
         <iterate property="keywords" conjunction="AND">
                      file_data LIKE #keywords[]#
                </iterate>
                -->
        
          ]]>
    </select>2009-08-20 11:56:02,546 ERROR [com.alt.rgs.search.action.SearchForKeywordAction]
     -
    --- The error occurred in com/alt/rgs/bean/SearchResultBean.xml.
    --- The error occurred while preparing the mapped statement for execution.
    --- Check the getText4.
    --- Check the parameter map.
    --- Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list fr
    om JavaBean. Cause java.lang.NumberFormatException: For input string: ""
      

  23.   

    For input string: ""
    是不是List中有空字符串,在调用SQL之前断点看下List里的每一个字符串是不是都有值,并且能转换成数值型!
      

  24.   

    我把<![CDATA[ ]]>去掉就OK了,难道IBATIS的动态SQL不能使用<![CDATA[ ]]>?
      

  25.   

    我晕死<![CDATA[ ]]>
    说明里面的东西不是xml,
    解析器也就不把它解析成xml的内容了。
    <>这样的东西都会把它当成sql的一部分,而不是ibatis的配置我晕死过去一会good luck