在DAO中使用预准备语句检索数据时出现问题

时间:2015-12-18 18:23:52

标签: java jdbc

public class StudentDAO extends ConnectorDAO {

    private List<StudentBean> studentList = new LinkedList<>();
    private StudentBean studentBean;

    public List<StudentBean> retrieveStudents() {

        Connection connection;

        try {
            String myQuery = "SELECT ?, ?, ? FROM Students";
            connection = getConnection() // getConnection() comes from superclass

            PreparedStatement preparedstatement = connection.prepareStatement(myQuery);
            preparedStatement.setString(1, "firstname");
            preparedStatement.setString(2, "lastname");
            preparedStatement.setString(3, "studentID");

            ResultSet resultSet = preparedStatement.executeQuery();

            while (resultSet.next()) {
                studentBean = new StudentBean();
                studentBean.setFirstName(resultSet.getString("firstname"));
                studentBean.setLastName(resultSet.getString("lastname"));
                studentBean.setID(resultSet.getInt("studentID"));
                studentList.add(studentBean);
            }
        } catch (Exception e) {
            // Error handling stuff
        } finally {
            // close connection, resultset and preparedstatement
        }

    } 
}

我的日食中出现错误。在我设置studentBean的ID的行上。我的数据库中studentID的数据类型是Int。我不知道如何检索它。谁能帮我?当我使用预准备语句中使用的参数进行查询时,它使用Statement对象时可以正常工作。

2 个答案:

答案 0 :(得分:2)

构建查询的代码不正确:

        String myQuery = "SELECT ?, ?, ? FROM Students";
        connection = getConnection() // getConnection() comes from superclass

        PreparedStatement preparedstatement = connection.prepareStatement(myQuery);
        preparedStatement.setString(1, "firstname");
        preparedStatement.setString(2, "lastname");
        preparedStatement.setString(3, "studentID");

不可能: 查询字符串的格式如下(示例):

String myQuery = "SELECT firstname, lastname, studentID FROM Students WHERE studentID=?";

参数仅用于不在列名,表名等上的变量。

因此,一旦您拥有类似的代码,就可以查询studentID(不是您的目标,只是为了示例):

preparedStatement.setInt(1, someStudentID);

preparedStatement发送给DBMS,然后DBMS将?替换为someStudentID的值。

答案 1 :(得分:0)

setString(或setInt中的setXXX或任何其他PreparedStatement)的含义是&#34;用适当的值替换相应的问号键入&#34 ;.所以这段代码:

String myQuery = "SELECT ?, ?, ? FROM Students";
connection = getConnection() // getConnection() comes from superclass

PreparedStatement preparedstatement = connection.prepareStatement(myQuery);
preparedStatement.setString(1, "firstname");
preparedStatement.setString(2, "lastname");
preparedStatement.setString(3, "studentID");

有效地创建以下查询:

SELECT 'firstname', 'lastname', 'studentID' FROM Students

现在,这告诉它从表中选择三个文字字符串。如果您在SQL命令行实用程序或类似的东西中运行此查询,您会发现结果是

firstname | lastname | studentID
firstname | lastname | studentID
firstname | lastname | studentID
firstname | lastname | studentID
...

而不是你的期望。由setString设置的任何内容都被解释为文字字符串 - 就好像它包含单引号一样。

因此,问号用于在语句中设置值,如果您在命令行实用程序中键入语句,则该值将是文字值。

因此,结果集的行是包含三个字符串firstnamelastnamestudentID的行。

现在,在下一段代码中:

while (resultSet.next()) {
    studentBean = new StudentBean();
    studentBean.setFirstName(resultSet.getString("firstname"));
    studentBean.setLastName(resultSet.getString("lastname"));
    studentBean.setID(resultSet.getInt("studentID"));
    studentList.add(studentBean);
}

在许多数据库系统中,您甚至无法使用getString("firstname"),因为来自文字查询的返回列名是任意的。但我想你的数据库系统实际上给返回列提供了与文字值相同的名称。因此,您可以检索firstnamelastname(但他们的内容不是学生姓名!它是文字字符串"firstname""lastname"),因为您正在使用getString

但是当你尝试使用getInt时,你运气不佳。由于您查询了文字字符串,因此您将获得三个字符串。第三列不是整数,而是文字字符串"studentID"。这是你遇到错误的地方。

所以你应该将你的查询改为

"SELECT firstname, lastname, studentID FROM Students"

这意味着在这种情况下你不一定需要准备好的陈述,但它也不会受到伤害。

那么你在哪里可以使用问号?

您在查询中需要文字值的任何地方。例如,如果您想知道一个人的出生年份与给定年份之间的差异,您可以写下:

SELECT year_of_birth - ? FROM people

然后使用setInt(1,1969)setInt(1,2001)使查询成为:

SELECT year_of_birth - 1969 FROM people

SELECT year_of_birth - 2001 FROM people

分别在预准备语句中,不能用问号替换数据库对象(如列和表)的实际名称(不是文字)。它们是查询计划本身的一部分。