【问题标题】:Prepared statement fails, but SQL console works准备好的语句失败,但 SQL 控制台工作
【发布时间】:2011-05-05 21:35:11
【问题描述】:

我正在为 uni 做一个项目(可能会在 14 小时内到期),我正处于一个症结所在。它是一个基于 web 的 web 商店,在 apache tomcat 和 derby 上运行在 eclipse 中。

我有一个准备好的语句来检查用户名和密码哈希,无论我尝试什么,这个语句都会返回 0 行。相同的 sql 在 sql 暂存器中运行并返回预期的内容。

我已经使用调试器检查了准备好的语句对象,并且查询似乎很好。文本中的 ? 仍然存在,而不是用变量填充,但这似乎很正常。我也尝试从控制台运行完全相同的手写 sql,但没有任何运气。

我在sql控制台运行的查询是

SELECT * FROM username WHERE username='user@system.com' AND passwordhash='passwordhash'

准备好的语句如下所示。

            PreparedStatement pstmt = db.prepareStatement("SELECT * FROM reallynice.username " +
                "WHERE emailaddress=?" +
                " AND passwordhash=?");

        pstmt.setString(1,username);
        pstmt.setString(2, username + ":" + passwordLogin);

我已经尝试了所有方法,并且已经用完了搜索。我知道这是一个 uni 项目,标准的答复是给人们看的地方。在这一点上,我需要勺子喂一条路才能走下去。

编辑这里有更多背景信息,我尝试在这个管道中运行一个已知的工作查询,它​​也无法返回任何行。

public static User getUser(String username, String passwordHash) {
    DBBean db = new DBBean();
    System.out.println("Logging in for username " + username + " and password " + passwordHash);
    try {
        ResultSet rs;

        PreparedStatement pstmt = db.prepareStatement("SELECT * FROM reallynice.username " +
                "WHERE emailaddress=?" +
                " AND passwordhash=?");

        pstmt.setString(1,username);
        pstmt.setString(2,passwordHash);
        //PreparedStatement pstmt = db.prepareStatement("SELECT * FROM reallynice.product");

        //PreparedStatement pstmt = db.prepareStatement("SELECT * FROM reallynice.username WHERE emailaddress='user@me.com' AND passwordhash='megahashstring'");

        rs = pstmt.executeQuery();
        System.out.println("Rows returned\t" + rs.getRow());

        if(rs.getRow() < 1)
            return null;

        int id = rs.getInt("uid");              
        String name = rs.getString("name");
        String emailaddress = rs.getString("emailaddress");
        String password = rs.getString("passwordhash"); 
        boolean isAdmin = false;

        pstmt = db.prepareStatement("SELECT * FROM reallnice.admin WHERE uid= ?");
        pstmt.setInt(1, id);
        rs = pstmt.executeQuery();

        if(rs.getMetaData().getColumnCount() > 0)
            isAdmin = true;
        return new User(id,isAdmin,name,emailaddress,password);

    } catch(Exception ex) {
        System.out.println(ex);
    }


    return null;
}

我还包括了我为此尝试过的其他查询。

【问题讨论】:

  • 你意识到你查询的是基于用户名的sql语句和你查询的是基于email地址的prepared语句吗?
  • 您可能需要回退变量并仅尝试“从 realnice.username 中选择 *”来验证您是否具有有效的连接等。然后对值​​进行硬编码。一旦你从那里回来,继续解决替代问题。
  • 也许可以通过将您的语句提炼到所需的最小值来开始调试。删除除select * from reallynice 之外的所有内容;在返回结果之后添加用户名参数,最后添加密码参数。 (可能是一些拼写错误,但您在准备好的语句中的查询与控制台版本不匹配。)
  • @Sam 是的,这是我在这里输入的错误,它们在系统中匹配。
  • 对数据库的其他查询工作,所以似乎连接在那里。我将在这个管道中运行一个工作查询。 EDIT 运行已知的有效查询也无法返回任何行。我为这个问题添加了更多上下文。

标签: java sql tomcat prepared-statement derby


【解决方案1】:

每当我看到有人有这样的经历:“无论我怎么尝试,这条语句都会返回 0 行”,我会立即想到两个可能的原因:

1) 您没有使用您认为的数据库。如果您说“;create=true”,Derby 的连接 URL 将非常乐意在您连接时创建一个新的空数据库,如果它在您期望的位置找不到现有数据库。此类问题源于对创建数据库的位置的混淆;将在任何目录中创建一个具有相对名称的数据库,该目录是获取该连接 URL 的 Derby 实例的 derby.system.home。因此,请检查您是否使用了不同的当前工作目录,或者由于某些其他原因连接到的数据库与您认为的不同。

2) 您没有使用您认为的架构。 Derby 会很高兴地创建多个模式,并且每个模式都有一组单独的表,所以如果您最初以用户 A 连接,然后以用户 B 连接,并且不发出 SET SCHEMA,那么用户 A 和用户 B拥有完全独立的表格集,因此您不会访问您认为的表格。因此,请检查您在连接到数据库时是否以同一用户身份连接并使用相同的架构。

【讨论】:

    【解决方案2】:

    尝试更改显示日志记录的方式

    System.out.println("Rows returned\t" + rs.getRow());
    

    getRow() 返回当前行号,而不是返回多少条记录。为了让用户 getRow() 计算结果集中的条目数,您需要将结果集的指针移动到最后一个条目。

    您还没有调用next(),这意味着您没有指向任何东西(这很可能是您总是将 0 视为数字的原因)。尝试使用

    while(rs.next()){ //go through the entire ResultSet} 
    

    if(rs.next()) { //access the first record in the ResultSet}
    

    总的来说,如果您将代码更改为以下内容,您可能会获得更好的结果。

    rs = pstmt.executeQuery();
    if(rs.next()){
        System.out.println("Processing Row " + rs.getRow());
        //continue on
    }else{
        System.out.println("No Records");
    }
    

    如果您已将用户名设置为唯一键的表,则可以确保这将返回 0 或 1 行。否则使用 while() 选项而不是 if()

    编辑:: 另外作为旁注,因为您没有调用 next()

    if(rs.getRow() < 1)
                return null;
    

    将始终为 0,从您的方法返回 null。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2017-12-09
      • 1970-01-01
      • 2014-01-29
      • 2014-03-16
      • 1970-01-01
      • 2010-09-08
      相关资源
      最近更新 更多