准备好的语句的 setString 不起作用

Posted

技术标签:

【中文标题】准备好的语句的 setString 不起作用【英文标题】:setString for prepared statement not working 【发布时间】:2014-10-09 12:20:00 【问题描述】:

我正在尝试对准备好的语句使用setString(index, parameter) 方法来创建ResultSet,但它似乎没有正确插入。我知道查询是正确的,因为我在后来的else 中使用了相同的查询(减去对setString 的需要)。这是我目前拥有的代码:

**据我了解,ps.setString(1, "'%" + committeeCode + "%'"); 应该替换查询中的?,但我的输出另有说明。任何帮助表示赞赏。

public String getUpcomingEvents(String committeeCode) throws SQLException
        Context ctx = null;
        DataSource ds = null;
        Connection conn = null;
        PreparedStatement ps  = null;
        ResultSet rs = null;

    StringBuilder htmlBuilder = new StringBuilder();
    String html = "";

    try 
        ctx = new InitialContext();
        ds = (DataSource) ctx.lookup("java:ConnectDaily");
        conn = ds.getConnection();

        if(committeeCode != null)
            //get all events
            String queryStatement = "SELECT " + 
                    .......
                    "WHERE c.calendar_id = ci.calendar_id AND c.short_name LIKE ? " + 
                    "AND ci.style_id = 0 " + 
                    "AND ci.starting_date > to_char(sysdate-1, 'J') " + 
                    "AND ci.item_type_id = cit.item_type_id " + 
                    "ORDER BY to_date(to_char(ci.starting_date), 'J')";




            ps = conn.prepareStatement(queryStatement);

            ps.setString(1, "'%" + committeeCode + "%'");
            System.out.println(queryStatement);

            rs = ps.executeQuery();

            if (rs != null)
                while(rs.next())
                    String com = rs.getString("name");
                    String comID = rs.getString("short_name");

                    String startTime = rs.getString("starting_time");
                    String endTime = rs.getString("ending_time");
                    String name = rs.getString("contact_name");
                    String desc = rs.getString("description");
                    String info = rs.getString("contact_info");
                    String date = rs.getString("directory");

                    htmlBuilder.append("<li><a href='?com="+committeeCode+"&directory=2014-09-10'>"+com+" - "+ date +" - "+startTime+" - "+endTime+"</a> <!-- Link/title/date/start-end time --><br>");
                    htmlBuilder.append("<strong>Location: </strong>"+comID+"<br>");
                    htmlBuilder.append("<strong>Dial-In:</strong>"+com+"<br>");
                    htmlBuilder.append("<strong>Part. Code:</strong>"+info+"<br>");
                    htmlBuilder.append("<a href='http://nyiso.webex.com'>Take me to WebEx</a>");
                    htmlBuilder.append("</li>");            
                    
            
            html = htmlBuilder.toString();

。 . .

    catch (NamingException e) 
        e.printStackTrace();
        //log error and send error email
     catch (SQLException e) 
        e.printStackTrace();
        //log error and send error email
    finally
        //close all resources here
        ps.close();
        rs.close();
        conn.close();
    
    return html;


输出

14:18:22,979 INFO  [STDOUT] SELECT  to_char(to_date(to_char(ci.starting_date), 'J'),'mm/dd/yyyy') as start_date,  to_char(to_date(to_char(ci.ending_date), 'J'),'mm/dd/yyyy') as end_date,  to_char(to_date(to_char(ci.starting_date), 'J'),'yyyy-mm-dd') as directory,  ci.starting_time,  ci.ending_time,  ci.description,  cit.description as location,  c.name,  c.short_name,  ci.add_info_url,  ci.contact_name,  ci.contact_info FROM calitem ci, calendar c, calitemtypes cit WHERE c.calendar_id = ci.calendar_id AND c.short_name LIKE ? AND ci.style_id = 0 AND ci.starting_date > to_char(sysdate-1, 'J') AND ci.item_type_id = cit.item_type_id ORDER BY to_date(to_char(ci.starting_date), 'J')

【问题讨论】:

System.out.println(queryStatement); 我认为要使您的 SQL 语句按预期工作,您需要从 setString 调用中删除引号:ps.setString(1, "%" + committeeCode + "%"); 我解决了这个问题。现在我在第 37 行得到一个空指针,它是初始的 `conn = ds.getConnection();` 处理来自ctx.lookup("java:ConnectDaily")NULL返回值:if ((ds = (DataSource) ctx.lookup("java:ConnectDaily")) == NULL) initializeDSLogic(); 如果你的意思是conn是一个空指针,处理它的大小写:if ((conn = ds.getConnection()) == NULL) connectDBLogic(); 【参考方案1】:

setString中的引号不需要:

ps.setString(1, "%" + committeeCode + "%");

此方法会将指定的String 绑定到第一个参数。它不会改变保存在queryStatement中的原始查询String

【讨论】:

【参考方案2】:

占位符仍然是 SQL 文本的一部分。

执行语句时传递绑定值;实际的 SQL 文本没有被修改。 (这是准备好的语句的一大优势:重复使用完全相同的 SQL 文本,并且我们避免了硬解析的开销。


另请注意,您在值中包含单引号,这有点奇怪。

如果要在 SQL 文本中替换绑定占位符,假设委员会代码包含 foo,则等效的 SQL 文本将是:

   AND c.short_name LIKE '''%foo%'''

将仅匹配以单引号开头和结尾的 c.short_name 值,并包含字符串 foo


(这看起来更像是 Oracle SQL 语法,而不是 mysql。)

【讨论】:

【参考方案3】:

我们知道在 setString 中我们只能传递字符串值,所以即使我们这样写代码:

String param="'%"+committeeCode+"%'";

如果你打印 param 的值,它会抛出错误,因此你不能在准备好的语句中使用它。

你需要稍微修改一下:

 String param="%"+committeeCode+"%";(Simpler one, other way can be used)
 ps.setString(1,param);

【讨论】:

以上是关于准备好的语句的 setString 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为啥准备好的语句在java中不起作用?

JDBC 准备好的语句不起作用 [关闭]

带有准备好的语句的 PDO bindParam() 不起作用

准备好的声明不起作用

插入选择不起作用

在 PHP 中为 MATCH AGAINST 准备的语句不起作用