JDBC--2 接口

JDBC常用的接口:

Statement 当在运行时使用静态 SQL 语句时(Statement接口不能接受的参数)

CallableStatement 当要访问数据库中的存储过程时(CallableStatement对象的接口还可以接受运行时输入参数)

PreparedStatement 当计划多次使用 SQL 语句时(PreparedStatement 接口接收在运行时输入参数)

1.statement的用法:

Statement stmt = null;
try {
   stmt = conn.createStatement( );
   . . .
} catch (SQLException e) {
   . . .
} finally {
   . . .
}
方法:

boolean execute(String SQL) 如果 ResultSet 对象可以被检索返回布尔值 true,否则返回 false。使用这个方法来执行 SQL DDL 语句,或当需要使用真正的动态 SQL

int executeUpdate(String SQL) 用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQLDDL(数据定义语言)语句。返回值是一个整数,指示受影响的行数(即更新计数)

ResultSet executeQuery(String SQL) 返回 ResultSet 对象。用于产生单个结果集的语句,例如 SELECT 语句

关闭statement:

Statement stmt = null;
try {
   stmt = conn.createStatement( );
   . . .
} catch (SQLException e) {
   . . .
} finally {
   stmt.close();
}

注:如果关闭了 Connection 对象首先它会关闭 Statement 对象,然而应该始终明确关闭 Statement 对象,以确保正确的清除。

2.preparedStatement的用法:

首先明确的是preparedStatement接口扩展了Statement接口,有利于执行多次使用的SQL语句,其用法和Statement是一样的,不过preparedStatement用于使用绑定变量重用的执行计划

PreparedStatement pstmt = null;<pre name="code" class="java">PreparedStatement prestmt = conn.prepareStatement("select banks from loan where loan_type=?");
prestmt.setString(1,loanType);

try { //在JDBC中所有的参数都被代表?符号,这是已知的参数标记。在执行SQL语句之前,必须提供值的每一个参数。 //通过 set 不同数据只需要生成一次执行计划,可以重用 String SQL = "Update Students SET age = ? WHERE id = ?"; pstmt = conn.prepareStatement(SQL); . . .} catch (SQLException e) {//setXXX()方法将值绑定到参数,其中XXX表示希望绑定到输入参数值的 Java 数据类型。如果忘了提供值,将收到一个 SQLException。 . . .} finally { //同理,我们需要关闭 PreparedStatement 对象 pstmt.close();}

那么问题来了(经常在面试中被问到的重点),我们在平时使用JDBC的时候为什么经常使用preparedStatement,而不是Statement呢??

1. PreparedStatement 可以写参数化查询,比 Statement 能获得更好的性能;

2. 对于 PreparedStatement 来说,数据库可以使用已经编译过及定义好的执行计划,这种预处理语句查询比普通的查询运行速度更快。

3. PreparedStatement 可以阻止常见的 SQL 注入式攻击。

4. PreparedStatement 可以写动态查询语句。

5. PreparedStatement 与 java.sql.Connection 对象是关联的,一旦你关闭了connection,PreparedStatement 也没法使用了。

6. “?” 叫做占位符。

7. PreparedStatement 查询默认返回 FORWARD_ONLY 的 ResultSet,你只能往一个方向移动结果集的游标。当然你还可以设定为其他类型的值如:”

CONCUR_READ_ONLY”。

8. 不支持预编译 SQL 查询的 JDBC 驱动,在调用connection.prepareStatement(sql)的时候,它不会把 SQL 查询语句发送给数据库做预处理,而是等到执行查询动作的时

(调用 executeQuery()方法时)才把查询语句发送个数据库,这种情况和使用 Statement 是一样的。

9. 占位符的索引位置从1 开始而不是 0, 如果填入 0 会导致*java.sql.SQLExceptioninvalid column index*异常。所以如果 PreparedStatement 有两个占位符,那么第一个参

的索引时 1,第二个参数的索引是 2。

3.CallableStatement的用法:

CallableStatement主要的作用是存储,有三个参数:

IN 它的值是在创建 SQL 语句时未知的参数,将 IN 参数传给 CallableStatement 对象是通过 setXXX() 方法完成的

OUT 其值由它返回的 SQL 语句提供的参数。从 OUT 参数的 getXXX() 方法检索值

INOUT 同时提供输入和输出值的参数,绑定的 setXXX() 方法的变量,并使用 getXXX() 方法检索值

面试要点:

PreparedStatement为什么要比Statement要快?

使用PreparedStatement的重要的优势就是其最佳的性能优势,SQL语句会预编译在数据库系统中,执行计划会被缓存起来,它允许数据库做参数化查询,比Statement的普

查询要快,其工作量少,原因是数据库对SQL语句的分析,编译,优化已经在第一次查询前完成了,减少了对数据库的读写次数即负载;

注意,在使用PreparedStatement查询的时候尽量使用查询参数化,不要使用字符串追加的形式,不然就没有任何的优势。

PreparedStatement prestmt = conn.prepareStatement("select banks from loan where loan_type=" + loanType);
PreparedStatement prestmt = conn.prepareStatement("select banks from loan where loan_type=?");
prestmt.setString(1,loanType);

PreparedStatement 可以防止 SQL 注入式攻击??

如果你是做 Java web 应用开发的, 那么必须熟悉那声名狼藉的 SQL 注入式攻击。在 SQL 注入攻击里,恶意用户通过 SQL 元数据绑定输入,比如:

某个网站的登录验证 SQL 查询代码为:

strSQL = "SELECT * FROM users WHERE name = '" + userName + "' and pw = '"+ passWord +"';"

恶意填入:

userName = "1' OR '1'='1";

passWord = "1' OR '1'='1";

那么最终 SQL 语句变成了:

strSQL = "SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1';"

因为 WHERE 条件恒为真,这就相当于执行:strSQL = "SELECT * FROM users;"

因此可以达到无账号密码亦可登录网站。如果恶意用户要是更坏一点,用户填入:

strSQL = "SELECT * FROM users;"

SQL 语句变成了:

strSQL = "SELECT * FROM users WHERE name = 'any_value' and pw = '';DROP TABLE users" 

这样一来,虽然没有登录,但是数据表都被删除了。然而使用 PreparedStatement 的参数化的查询可以阻止大部分的 SQL 注入。在使用参数化查询的情况下,数据库系

(eg:MySQL)不会将参数的内容视为SQL 指令的一部分来处理,而是在数据库完成 SQL 指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数

库所运行。

补充:避免 SQL 注入的第二种方式:

在组合 SQL 字符串的时候,先对所传入的参数做字符取代(将单引号字符取代为连续 2 个单引号字符,因为连续 2 个单引号字符在 

SQL 数据库中会视为字符中的一个单引号字符,譬如:

strSQL = "SELECT * FROM users WHERE name = '" + userName + "';"

传入字符串:

userName = " 1' OR 1=1 "

把 userName 做字符替换后变成:

userName = " 1'' OR 1=1"

最后生成的 SQL 查询语句为:
strSQL = "SELECT * FROM users WHERE name = '1'' OR 1=1'

这样数据库就会去系统查找 name 为“1′ ‘ OR 1=1”的记录,而避免了SQL 注入。比起凌乱的字符串追加似的查询,PreparedStatement 查询可读性更好、更安全。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值