statement和prepareStatement 的区别

Posted 哪 吒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了statement和prepareStatement 的区别相关的知识,希望对你有一定的参考价值。

🍅 Java基础教程系列: Java基础教程系列

🍅 Java学习路线总结:搬砖工逆袭Java架构师

🍅 Java经典面试题大全:10万字208道Java经典面试题总结(附答案)

🍅 简介:Java领域优质创作者🏆、CSDN哪吒公众号作者✌ 、Java架构师奋斗者💪

🍅 扫描主页左侧二维码,加入群聊,一起学习、一起进步 

🍅 欢迎点赞 👍 收藏 ⭐留言 📝   

一、【粉丝福利】

送书啦,大家期待已久的Vue!

本次活动送书规则:

【送书啦】

1、社区积分榜前5名,随机抽取一名幸运者

2、社区积分榜6-15名,随机抽取一名幸运者

3、社区积分榜16-30名,随机抽取一名幸运者

【赚取积分方式】哪吒社区内发帖、点赞、评论都可赢取积分!

🍅 社区入口:哪吒社区


🍅 哪吒社区技能树打卡贴:【打卡贴 day7】String、StringBuilder、StringBuffer详解

【抽取方式】Java随机函数;

【抽取时间】2021年11月2日 周二 21点整,抽取结果会在【哪吒微信一群、二群、三群】同时公布。

以下图书,四选一!

1、Vue.js全家桶零基础入门到进阶项目实战
2、亿级流量Java高并发与网络编程实战
3、Web前端性能优化
4、R语言数据高效处理指南

二、简介

它们都是接口:

  • Statement继承自Wrapper
  • PreparedStatement继承自Statement
  • CallableStatement继承自PreparedStatement

Statement:直接操作sql,不进行预编译,不带参数;

PreparedStatement:进行预编译,可带参数;

CallableStatement:执行存储过程;

SQL的执行需要编译和解析。

Statement每次的执行都需要编译SQL。

PreparedStatement会预编译,会被缓冲,在缓存区中可以发现预编译的命令,虽然会被再次解析,但不会被再次编译,能够有效提高系统性能。

三、statement的四种形式

  • executeQuery
  • executeUpdate
  • execute
  • Batch 

1、executeQuery

用于产生单个结果集的语句,用于执行 SELECT 语句(SELECT无疑是是使用最多的 SQL 语句) ,返回值为ResultSet。

2、executeUpdate

用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。

executeUpdate 的返回值是一个整数,指示受影响的行数(即更新计数)。对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。

3、execute

用于执行返回多个结果集、多个更新计数或二者组合的语句。execute对与结果的处理比较麻烦

execute方法应该仅在语句能返回多个ResultSet对象、多个更新计数或ResultSet对象与更新计数的组合时使用。

返回值指示类型情况:如果下一个结果为 ResultSet 对象,则返回 true;如果其为更新计数或者不存在更多结果,则返回 false。

Statement stmt = conn.createStatement();
if(stmt.execute(sql)){
    ResultSet rs = stmt.getResultSet();
}else{
    log.info("受影响的行 {}", stmt.getUpdateCount());
}

(1)ResultSet getResultSet()

以 ResultSet 对象的形式获取当前结果

(2)int getUpdateCount()

以更新计数的形式获取当前结果;如果结果为 ResultSet 对象或没有更多结果,则返回 -1

(3)boolean getMoreResults()

移动到此 Statement 对象的下一个结果,如果其为 ResultSet 对象,则返回 true,并隐式关闭利用方法 getResultSet 获取的所有当前 ResultSet 对象

(4)boolean getMoreResults(int current)

将此 Statement 对象移动到下一个结果,根据给定标志指定的指令处理所有当前 ResultSet 对象;如果下一个结果为 ResultSet 对象,则返回 true

(5)default long getLargeUpdateCount()

4、Batch

(1)void addBatch(String sql)

将给定的 SQL 命令添加到此 Statement 对象的当前命令列表中

(2)void clearBatch()

清空此 Statement 对象的当前 SQL 命令列表

(3)int[] executeBatch()

 将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组                 

对于batch操作,简单说就是有一个列表,保存了执行命令。

add是添加方法,clear就是清空方法,execute就是执行列表内命令。

如下面示例,将1000个“张三”分十次插入数据库:

for(int i=0;i<1000;i++){
    String sql = "insert into user(id,name,age) values (i,'张三"+i+"',18)";
    stmt.addBatch(sql);
    if(i%100 == 0){
        stmt.executeBatch();
        stmt.clearBatch();
    }
}

四、PreparedStatement常用方法

1、boolean execute()

在此 PreparedStatement 对象中执行 SQL 语句,该语句可以是任何种类的 SQL 语句。

ResultSet executeQuery()

在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的 ResultSet 对象。

2、int executeUpdate()

在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 SQL 数据操作语言(Data Manipulation Language,DML)语句,比如 INSERT、UPDATE 或 DELETE 语句;或者是无返回内容的 SQL 语句,比如 DDL 语句。

3、void addBatch()

将一组参数添加到此 PreparedStatement 对象的批处理命令中。

4、void clearParameters()

立即清除当前参数值。

5、ResultSetMetaData getMetaData()

获取包含有关 ResultSet 对象列信息的 ResultSetMetaData 对象,ResultSet 对象将在执行此 PreparedStatement 对象时返回

6、ParameterMetaData getParameterMetaData()

获取此 PreparedStatement 对象的参数的编号、类型和属性。

五、PreparedStatement代码实例

String sql = "insert into user(id,name,age) values (?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql, Statement.NO_GENERATED_KEYS);
ps.setInt(1,1);
ps.setString(2,"哪吒");
ps.setInt(3,18);
ps.executeUpdate();

六、使用PreparedStatement能够预防SQL注入攻击

假如登录SQL为select * from user where name='zs' and password='123' ,如果在登录框密码处输入 “123 or 1=1”,那么SQL就成为了

select * from user where name='zs and password='123' or 1=1  ,这就是SQL注入。

所谓SQL注入就是将SQL语句片段插入到被执行的语句中,把SQL命令插入到Web表单提交或者输入域名或者页面请求的查询字符串,最终达到欺骗服务器,达到执行恶意SQL命令的目的。

PreparedStatement通过预编译,原有的SQL语句中的参数转换为占位符?的形式,相当于变成了填空题,不管你输入的内容是什么,都是作为参数,而不可能作为SQL的一部分

(要注意 #与$的区别)

你把密码输入为'123 or 1=1'然后提交,他会转换为  select * from user where name='zs and password='123 or 1=1',输入内容都转换为纯粹参数。

六、CallableStatement
CallableStatement继承自prepareStatement,实现了存储过程函数调用的方法以及对于输出的处理。

CallableStatement调用存储过程和函数,一个很重要的部分就是输出的处理。

在JDBC中需要使用registerOutParameter将参数注册为输出,registerOutParameter的责任就是申明XXX参数是一个输出。

对于这个参数可以使用int  parameterIndex 下标索引(1开始)也可以使用String parameterName来指明,对于参数对应的类型也需要指明。

七、xml中的statementType

在mapper文件中可以使用statementType标记使用什么的对象操作SQL语句。

xml文件中通过statementType参数,选择适合的对象。

statementType取值说明:

  1. STATEMENT:直接操作sql,不进行预编译,不带参数;
  2. PREPARED:进行预编译,可带参数;
  3. CALLABLE:执行存储过程;

注意:如果只为STATEMENT,那么sql就是直接进行的字符串拼接,这样为字符串需要加上引号,如果为PREPARED,是使用的参数替换,也就是索引占位符,我们的#会转换为?再设置对应的参数的值。

🍅 Java基础教程系列: Java基础教程系列

🍅 Java学习路线总结:搬砖工逆袭Java架构师

🍅 Java经典面试题大全:10万字208道Java经典面试题总结(附答案)

🍅 简介:Java领域优质创作者🏆、CSDN哪吒公众号作者✌ 、Java架构师奋斗者💪

🍅 扫描主页左侧二维码,加入群聊,一起学习、一起进步 

🍅 欢迎点赞 👍 收藏 ⭐留言 📝   

添加微信,备注1024,赠送Java学习路线思维导图 

以上是关于statement和prepareStatement 的区别的主要内容,如果未能解决你的问题,请参考以下文章

7-22总结

JDBC预编译statement(preparedstatement)和statement的比较execute与executeUpdate的区别

Statement和ResultSet

JDBC学习笔记——Statement和ResultSet

Java_JDBC使用Statement和PreparedStatement

Java中PreparedStatement和Statement的用法区别