【问题标题】:How can I only get 1 element from a SQL Database?如何仅从 SQL 数据库中获取 1 个元素?
【发布时间】:2020-05-02 16:26:17
【问题描述】:

我有一个小问题。我写了一个方法,其中我有一个 SQL 查询,应该在 2 个参数之后输出一个正确的字符串。但是,在调试时,结果不是正确的元素。我不知道为什么会这样。

public static String findRightTemplate(String user_name, int template_id)
  throws Exception {


        Connection conn = DriverManager.getConnection(
                "xxx", "xxx", "xxx");
        Statement st = conn.createStatement();

        st = conn.createStatement();
        ResultSet rs = st.executeQuery(
          "SELECT template FROM templates " +
          "where template_id=template_id AND user_name=user_name"
          );

        String temp="";
        while(rs.next())
        {
            temp=rs.getString("template");
        }


        rs.close();
        st.close();
        conn.close();

我要求提供用户名和模板 ID,我只想从模板列中获取一个元素。 SQL 查询是正确的。我已经测试过了。但似乎查询贯穿所有具有相同用户名的元素。结果,我只得到最后一个元素,而不是正确的。

更新

【问题讨论】:

  • 您的 SQL 服务器将看到以下查询:SELECT template FROM templates where template_id=template_id AND user_name=user_name 您的 WHERE 条件将始终为真(嗯...除了 NULL)。跨度>
  • "结果,我只得到了最后一个元素,而不是正确的那个。" ——这没有意义。关系表没有固有的行顺序;在没有ORDER BY 子句的情况下,查询可以按任何顺序返回行,这也可以随着时间而改变。
  • 使用PreparedStaement 并参数化您的查询。
  • @SteveLovell 你为什么要这么建议?
  • 请告诉我这不是生产代码。像这样组装你的查询字符串会让你对SQL injection attacks敞开心扉。 (必填xkcd

标签: java sql


【解决方案1】:

目前您不使用查询中的方法参数。正如已经建议的那样,您应该使用PreparedStatement 来解决这个问题。你基本上应该做到以下几点:

public static String findRightTemplate(String userName, int templateId) throws SQLException {
    try (final Connection connection = DriverManager.getConnection("...")) {
        final PreparedStatement preparedStatement = connection.prepareStatement(
                "SELECT template " +
                "FROM templates " +
                "WHERE user_name = ? " +
                "AND template_id = ? " +
                "LIMIT 1"
        );

        preparedStatement.setString(1, userName);
        preparedStatement.setInt(2, templateId);

        final ResultSet resultSet = preparedStatement.executeQuery();

        if (resultSet.next()) {
            return resultSet.getString(1);
        }
    }

    return null;
}

如果您不使用 PreparedStatement 并按照 cmets 中的建议手动构建查询,您的应用程序可能容易受到 SQL 注入攻击。

【讨论】:

  • 1 和 2 交换。而connection、preparedStatement和resultSet应该是close()d。最好使用try (Connection connection = ...) { 等。
  • 谢谢,好收获!您是绝对正确的,但是为了支持一个更简单的示例,我省略了 JDBC 样板。就我个人而言,我什至不会直接使用 JDBC,而是使用 Spring 的 JDBCTemplate 之类的东西。
猜你喜欢
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
  • 2019-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多