Java-SQL-操作指南深入理解-Statement-用法与优化
目录
《Java SQL 操作指南:深入理解 Statement 用法与优化》
在 Java 数据库编程中,
Statement
是用于执行 SQL 语句的接口,允许程序与数据库进行交互。本文将详细介绍
Statement
的基本概念、常见用法以及
PreparedStatement
和
CallableStatement
等相关接口。
1. Statement 基本介绍
Statement
接口继承了
AutoCloseable
和
Wrapper
接口,使其具备自动关闭和封装功能。
AutoCloseable
:提供close()
方法,确保Statement
在不再使用时释放资源。Wrapper
:提供isWrapperFor(Class<?>)
和unwrap(Class<T>)
方法,允许Statement
作为其他数据库 API 的封装。
此外,
Statement
还包含多个重要属性,如
cursorName
、
poolable
、
connection
等。
Statement
是 JDBC 提供的用于执行 SQL 语句的接口,主要特点如下:
- 适用于执行静态 SQL 语句,每次执行都需要编译。
- 通过
executeQuery()
执行查询语句,返回ResultSet
。 - 通过
executeUpdate()
执行更新语句,返回影响的行数。 - 存在 SQL 注入风险,建议使用
PreparedStatement
代替。
2. Statement 的基本用法
package JDBC;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
import java.util.Scanner;
//JDBC注入机制演示
public class Statement_ {
public static void main(String[] args) throws Exception {
// Class.forName("com.mysql.jdbc.Driver");
Scanner scanner = new Scanner(System.in);
System.out.println("Enter SQL nameusr statement");
String username =scanner.nextLine();
System.out.println("Enter SQL pwd statement");
String pwd =scanner.nextLine();
Properties properties = new Properties();
properties.load(new FileInputStream("src\\JDBC\\mysql.properties"));
String url = (String) properties.get("url");
String user =(String) properties.get("user");
String password =(String) properties.get("password");
String driver =(String) properties.get("driver");
// 实例化
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, user, password);
// 得到statement
Statement statement = connection.createStatement();
// 组织查询语句
String sql = "select * from sql_injection where NAME='"+username+"'and pwd = '"+pwd+"';" ;
System.out.printf(sql+"\n");
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()) {
System.out.println("查询成功");
}
else {
System.out.println("查询失败");
}
// 关闭连接,安全操作
resultSet.close();
statement.close();
connection.close();
}
}
2.1 主要方法
execute(String sql)
- 执行 SQL 语句,返回
boolean
,如果执行的是查询语句,返回true
,否则返回false
。
executeQuery(String sql)
- 仅用于
SELECT
语句,返回ResultSet
。
executeUpdate(String sql)
- 仅用于
INSERT
、UPDATE
或DELETE
语句,返回受影响的行数。
addBatch(String sql)
- 添加 SQL 语句到批处理命令中。
executeBatch()
- 执行批处理命令,返回每条 SQL 语句影响的行数。
clearBatch()
- 清除已添加的批处理命令。
setQueryTimeout(int seconds)
- 设置查询超时时间。
getMoreResults()
- 检查是否存在多个
ResultSet
。
close()
- 关闭
Statement
,释放资源。
2.2 执行更新操作
可以使用
executeUpdate()
进行
INSERT
、
UPDATE
和
DELETE
操作,例如:
Statement stmt = conn.createStatement();
int rowsAffected = stmt.executeUpdate("UPDATE users SET age = 30 WHERE id = 1");
System.out.println("更新影响的行数: " + rowsAffected);
3. Statement 的问题与优化
3.1 SQL 注入风险
使用
Statement
直接拼接 SQL 语句可能会导致 SQL 注入攻击,例如:
USE mydatabase;
SHOW DATABASES;
SHOW TABLES;
CREATE TABLE sql_injection ( -- 管理表
NAME VARCHAR(32) NOT NULL UNIQUE,
pwd VARCHAR(32) NOT NULL DEFAULT ''
)CHARACTER SET utf8;
DROP TABLE sql_injection;
DESC sql_injection;
INSERT INTO sql_injection VALUES( 'wangya' ,'1314520'
);
SELECT * FROM sql_injection;
SELECT * FROM sql_injection
WHERE NAME='wangya' AND pwd='1314520';
-- sql 注入演示
-- 用户输入密码为: 1' or
-- 输入密码为:or '1'= '1
SELECT * FROM sql_injection
WHERE NAME='1' OR' or AND pwd='OR '1'= '1';
SELECT * FROM sql_injection
WHERE NAME='wangya' OR pwd='1314520' OR '1'='1' ;
以上代码可能被攻击者利用,绕过密码验证。
总结
Statement
是 Java 数据库操作的基本接口,但由于其存在 SQL 注入风险,在实际开发中推荐使用
PreparedStatement
。此外,
CallableStatement
适用于调用存储过程,提高数据库访问效率。了解并正确使用这些接口,可以提升数据库操作的安全性和性能。