2011-05-05 65 views
0

我正在为uni项目工作(恰好在14小时内到期),我处于一个棘手的问题。它是一个基于web的网上商店,运行在apache tomcat和derby的eclipse上。准备语句失败,但SQL控制台工作

我有一个准备语句,检查用户名和passwordhash,不管我尝试这个语句返回0行。同样的sql在sql暂存区中运行并返回预期的结果。

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

我在sql控制台运行查询是

SELECT * FROM username WHERE username='[email protected]' AND passwordhash='passwordhash' 

的准备statments这个样子。

  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='[email protected]' 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; 
} 

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

+0

你知道你正在查询的sql语句是基于用户名和基于电子邮件地址查询的准备好的语句吗? – 2011-05-05 21:40:26

+0

您可能需要退出变量并尝试'select * from reallynice.username'来验证您是否拥有有效的连接等。然后对这些值进行硬编码。一旦你从那里回来,转向替代问题。 – Justin 2011-05-05 21:41:06

+0

也许可以通过将您的语句提取到需要的最小值来开始调试。除了'select * from reallynice'之外,删除所有内容;在返回结果后,添加用户名参数,最后输入密码参数。 (也许这是一些错别字,但是你在准备好的语句中的查询与控制台版本不匹配。) – 2011-05-05 21:44:51

回答

1

每当我看到有这样的经历的人:“不管我试试这个语句返回0行”,也有说马上想到的两个可能的原因:您没有使用

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

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

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(rs.getRow() < 1) 
      return null; 

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