PreparedStatement和Statement的区别

1.PreparedStatement接口继承Statement,PreparedStatement实例包含已经编译的sql语句,所以其执行速度要快于Statement对象
2.作为Statement的子类PreparedStatement继承了Statement的所有功能,三种方法 execute,executeQuery,executeUpdate已被更改以使用之不再需要参数
3.在jdbc的应用中任何时候都不要使用Statement 其原因如下:
一.代码的可读性和可维护性太差,Statement需要不断的拼接,PreparedStatement不会
二.PreparedStatement可以尽大可能的提高性能,DB有缓存机制的,相同的预编译语句再次出现被调用时不会再次重新编译
三.最重要的一点是极大的提高了安全性,Statement容易被sql注入,而PreparedStatement传入的内容不会和sql发生任何匹配关系
java的api提供了三种执行sql的方法:PreparedStatement是其中一种,另外还有,Statement和CallableStatement,其中Statement用于通用查询,
PreparedStatement用于执行参数化查询,而CallableStatement则是用于执行存储过程,一般我们执行业务逻辑的sql都会使用PreparedStatement
而不会选择使用Statement 其中也是有原因的.
为什么要使用PreparedStatement,它到底有什么好处,又是如何避免sql注入问题的
PreparedStatement 是java.sql包下面的一个接口,用来来执行slq查询语句,在我们获得数据库连接后直接调用connection.PreparedStatement(sql)方法就可以获取到PreparedStatement对象,
这时数据库系统会对传入的sql语句进行预编译处理,也就是说在代码运行到此处的时候PreparedStatement会对写好的sql进行编译,而且这条预编译的sql查询语句会被数据库缓存当再次被调用时,
就不会再重新编译,这比Statement对象查询速度更快
package com.mybatis.excample.jdbc;

import java.sql.*;

/**
 * Created by Administrator on 2018/2/7.
 */
public class jdbcTest {

	public static void main(String[] args) {

		String url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true";
		String name="root";
		String password="root";
		try {
			//加载数据库驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获取数据库连接
			Connection connection = DriverManager.getConnection(url, name, password);
			String sql="SELECT * FROM user u WHERE 1=1 AND u.name =?";
			//获取preparedStatement对象 这次数据库会先将slq编译
			PreparedStatement preparedStatement = connection.prepareStatement(sql);
			//使用占位符的方式传递参数
			preparedStatement.setString(1,"xxx");
			ResultSet resultSet = preparedStatement.executeQuery();
			while (resultSet.next()){
				ResultSetMetaData metaData = resultSet.getMetaData();
				int columnCount = metaData.getColumnCount();
				for (int i=1;i<columnCount;i++){
					String columnTypeName = metaData.getColumnTypeName(i);
					Object object = resultSet.getObject(i);
					System.out.println(object);
				}
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}


	}
}
 使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入。在使用参数化查询的情况下,数据库系统(eg:MySQL)不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。

关于PreparedStatement接口,需要重点记住的是:
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.SQLException invalid column index*异常。所以如果PreparedStatement有两个占位符,那么第一个参数的索引时1,第二个参数的索引是2.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值