准备好的语句失败,但SQL控制台正常工作

时间:2011-05-05 21:35:11

标签: java sql tomcat prepared-statement derby

我正在为uni进行一个项目(恰好在14个小时内到期),我处在一个棘手的问题上。它是一个基于web的网上商店,在apache tomcat和derby上运行。

我有一个准备好的语句,用于检查用户名和密码,无论我尝试此语句返回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);

我正处于尝试所有事情的地步,并且已经完成了搜索。我知道这是一个单项目,标准答案是让人们去看看。在这一点上,我需要用勺子喂一条小路。

编辑以下是更多背景信息,我尝试在此管道中运行已知的工作查询,但也无法返回任何行。

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;
}

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

2 个答案:

答案 0 :(得分:1)

每当我看到某人有这样的经历时:“无论我尝试什么,这句话都会返回0行,”有两个可能的原因立即浮现在脑海中:

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

2)您没有使用您认为自己的架构。 Derby非常乐意创建多个模式,每个模式都有一组单独的表,所以如果你最初以用户A身份连接,然后以用户B身份连接,并且不发出SET SCHEMA,那么用户A和用户B具有完全独立的表集,因此您将无法访问您认为自己的表。因此,请检查您是否以同一用户身份进行连接,并在连接到数据库时使用相同的架构。

答案 1 :(得分:0)

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

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。