演示业务中必须使用Statement完成字符串的拼接

本文探讨了在Java中使用PreparedStatement和Statement处理SQL查询时遇到的问题。当尝试用PreparedStatement按用户输入排序时,由于SQL语法错误导致执行失败。问题在于?占位符将输入作为字符串处理,不适合动态SQL片段。因此,改用Statement进行字符串拼接解决了问题,但同时也暴露了SQL注入的风险。文章强调了在处理用户输入时预防SQL注入的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接上篇:java.sql.SQLSyntaxErrorException: Unknown column ‘xxx‘ in ‘where clause‘问题解决及防止SQL注入
演示业务中必须使用Statement完成字符串的拼接.

1、需求:

输入desc,对表中的数据按名字降序排序;
输入asc,对表中的数据按名字升序排序。

2、代码:

2.1 尝试用PreparedStatement完成

package com.sunny;
import java.sql.*;
import java.util.Scanner;
/**
 * 尝试用PreparedStatement完成:输入desc,对表中的数据按名字降序排序
 *                   		   输入asc,对表中的数据按名字升序排序
 */
public class JDBCTest08 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入关键字:asc升序输出,desc降序输出");
        String kw = scanner.nextLine();
        try {
            //注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //获取连接
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mytest?serverTimezone=Asia/Shanghai","root","123456");
            //获取预编译的数据库操作对象
            String sql = "select * from user order by username ?";
            ps = conn.prepareStatement(sql);
            //传值
            ps.setString(1, kw);
            //执行sql
            rs = ps.executeQuery();
            while (rs.next()){
                System.out.println(rs.getInt("id") + "--"
                               + rs.getString("username") + "--"
                               + rs.getString("password"));
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

运行结果:

D:\Java\jdk1.8.0_202\bin\java.exe...
输入关键字:asc升序输出,desc降序输出
asc
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''asc'' at line 1
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1003)
	at com.sunny.JDBCTest08.main(JDBCTest08.java:30)

Process finished with exit code 0

2.2 结论

通过上面可以发现:
用PreparedStatement无法完成的,因为用?的话会以字符串的形式传入desc/asc,导致拼接的sql语句出现语法问题,所以报错。

2.3 改用Statement

package com.sunny;
import java.sql.*;
import java.util.Scanner;
/**
 * 利用Statement完成:输入desc,对表中的数据按名字降序排序
 *                   输入asc,对表中的数据按名字升序排序
 */
public class JDBCTest08 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入关键字:asc升序输出,desc降序输出");
        String kw = scanner.nextLine();
        try {
            //注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //获取连接
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mytest?serverTimezone=Asia/Shanghai","root","123456");
            //获取预编译的数据库操作对象
            String sql = "select * from user order by username " + kw ; //进行字符串拼接
            //执行sql
            stmt = conn.createStatement();

            rs = stmt.executeQuery(sql);
            while (rs.next()){
                System.out.println(rs.getInt("id") + "--"
                        + rs.getString("username") + "--"
                        + rs.getString("password"));
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

运行结果:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ED_Sunny小王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值