prepareStatement与Statement的区别

2023-05-16

 

prepareStatement与Statement的区别

1.区别:

stmt=conn.CreateStatement();
resultSet rs=stmt.executeQuery(sql);
上面是statement的用法
============================
下面是PrepareStatement的用法
ptmt=conn.PreparedStatement(sql);
resultSet rs=ptmt.executeQuery();
================================
Statement 是PreparedStatement的父类
还有就是sql放置的位置不同 。

在开发中一般用PrepareStatement

 

jdbc(java database connectivity,java数据库连接)的api中的主要的四个类之一的java.sql.statement要求开发者付出大量的时间和精力。在使用statement获取jdbc访问时所具有的一个共通的问题是输入适当格式的日期和时间戳:2002-02-05 20:56 或者 02/05/02 8:56 pm。
通过使用java.sql.preparedstatement,这个问题可以自动解决。一个preparedstatement是从java.sql.connection对象和所提供的sql字符串得到的,sql字符串中包含问号(?),这些问号标明变量的位置,然后提供变量的值,最后执行语句,例如:
stringsql = "select * from people p where p.id = ? and p.name = ?";
preparedstatement ps = connection.preparestatement(sql);
ps.setint(1,id);
ps.setstring(2,name);
resultset rs = ps.executequery();
使用preparedstatement的另一个优点是字符串不是动态创建的。下面是一个动态创建字符串的例子:
stringsql = "select * from people p where p.i = "+id;

这允许jvm(javavirtual machine,java虚拟机)和驱动/数据库缓存语句和字符串并提高性能。
preparedstatement也提供数据库无关性。当显示声明的sql越少,那么潜在的sql语句的数据库依赖性就越小。
由于preparedstatement具备很多优点,开发者可能通常都使用它,只有在完全是因为性能原因或者是在一行sql语句中没有变量的时候才使用通常的statement。
一个完整的preparedstatement的例子:
package jstarproject;
import java.sql.*;
public class mypreparedstatement {
private final string db_driver="com.microsoft.jdbc.sqlserver.sqlserverdriver";
private final string url = "jdbc:microsoft:sqlserver://127.0.0.1:1433;databasename=pubs";
public mypreparedstatement()
{
}
public void query() throws sqlexception{
connection conn = this.getconnection();
string strsql = "select emp_id from employee where emp_id = ?";
preparedstatement pstmt = conn.preparestatement(strsql);
pstmt.setstring(1,"pma42628m");
resultset rs = pstmt.executequery();

while(rs.next()){
string fname = rs.getstring("emp_id");
system.out.println("the fname is " + fname);
}
rs.close();
pstmt.close();
conn.close();
}
private connection getconnection() throws sqlexception{
// class.
connection conn = null;
try {
class.forname(db_driver);
conn = drivermanager.getconnection(url,"sa","sa");
}
catch (classnotfoundexception ex) {}
return conn;
}
//main
public static void main(string[] args) throws sqlexception {
mypreparedstatement jdbctest1 = new mypreparedstatement();
jdbctest1.query();
}
}


为什么要始终使用PreparedStatement代替Statement?为什么要始终使用PreparedStatement代替Statement?


在JDBC应用中,如果你已经是稍有水平开发者,你就应该始终以PreparedStatement代替Statement.也就是说,在任何时候都不要使用Statement.
基于以下的原因:
一.代码的可读性和可维护性.
虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次:

stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");

perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate();

不用我多说,对于第一种方法.别说其他人去读你的代码,就是你自己过一段时间再去读,都会觉得伤心.

二.PreparedStatement尽最大可能提高性能.
每一种数据库都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:
insert into tb_name (col1,col2) values ('11','22');
insert into tb_name (col1,col2) values ('11','23');
即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存.

当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.

三.最重要的一点是极大地提高了安全性.

即使到目前为止,仍有一些人连基本的恶义SQL语法都不知道.
String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";
如果我们把[' or '1' = '1]作为varpasswd传入进来.用户名随意,看看会成为什么?

select * from tb_name = '随意' and passwd = '' or '1' = '1';
因为'1'='1'肯定成立,所以可以任何通过验证.更有甚者:
把[';drop table tb_name;]作为varpasswd传入进来,则:
select * from tb_name = '随意' and passwd = '';drop table tb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行.

而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.只要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的statement,有可能要对drop,;等做费尽心机的判断和过虑.

上面的几个原因,还不足让你在任何时候都使用PreparedStatement吗

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

prepareStatement与Statement的区别 的相关文章

  • ffmpeg命令行使用

    查看视频信息 ffmpeg i 视频名字 视频名字这里输入前几个字符按 tab 键可以自动补全 返回结果 xff1a 红框之内的内容没什么用 编码器 xff1a encoder Lavf57 25 100 持续时间 xff1a Durati
  • 基于JAVA的志愿者管理系统(最新)

    个人毕业设计 xff0c 喜欢的私聊 目录 基于JAVA的志愿者管理系统 3 专业 xff1a 学号 xff1a 学生姓名 xff1a 指导老师 xff1a 3 1 引言 4 1 1 项目开发的背景 4 1 2本文的主要工作 5 1 3本课

随机推荐

  • 追风筝的人:变质的友谊

    每个人心中都有一段不可言说的故事 在我们的岁月里 xff0c 那些朋友玩伴早已经消失在了我们的生活之中 但是那些共同的记忆还保留在我们的心中 追风筝的人 这是一本描述友谊的书籍 xff0c 能够给我们的心灵带来一丝的慰籍 哈桑在一次逃避中
  • 题目:判断101-200之间有多少个素数,并输出所有素数。

    题目 xff1a 判断101 200之间有多少个素数 xff0c 并输出所有素数 分析 xff1a 不能被2整除的称为质数 错解 xff1a for int i 61 101 i lt 61 200 i 43 43 if i 2 61 0
  • iOS总结

    1 设置UILabel行间距 NSMutableAttributedString attrString 61 NSMutableAttributedString alloc initWithString label text NSMutab
  • 最大公约数

    题目 xff1a 输入两个正整数m和n xff0c 求其最大公约数 分析 使用辗转相除法 竞相减损法 比如36和24的最大公约数是12 36 24 61 12 24 12 61 0 xff1b 所以12是36和24的最大公约数 比如48和3
  • SpringMVC中可以判断Controller中传来的参数是否为空方法

    package org swinglife controller import org springframework stereotype Controller import org springframework web bind an
  • HashMap的简单使用之remove的使用(三)

    remove方法可以删除其中的属性值
  • 新手最应该看的Mybatis中xml的分页查询sql语句

    研究了一整天 xff0c 终于弄明白了 Mybatis中 xml 的分页查询 sql 语句 xff1a lt 根据页数进行排序 gt lt select id 61 34 selectStudentByMap 34 resultType 6
  • 王昕的 java 下Excel的导入和导出,数据校验

    Apache POI是Apache开发的开源的跨平台的 Java API xff0c 提供API给Java程序对Microsoft Office格式档案进行各种操作 POI中Excel操作很简单 xff0c 主要类有 HSSFWorkboo
  • ModuleNotFoundError: No module named 'urllib2'

    历尽千辛万苦 xff0c 终于在Eclipse上安装好了python的编译工具了 https blog csdn net zrcshendustudy article details 82120397 正准备来一个爬虫程序入门的时候 xff
  • AttributeError: module 'pip' has no attribute 'pep425tags'

    情境再现 xff1a AttributeError module 39 pip 39 has no attribute 39 pep425tags 39 分析问题 xff1a 百度可知是Win32和Win64的输入命令各有所不同 解决问题
  • maven中的pom导入jackson包存在的问题,miss the jar

    情境再现 xff1a 之前导Jackson包的时候 xff0c 一直在dependency处有个错号 xff0c 我之前导的是2 6 0版本 分析问题 xff1a 网上好多说是maven文件没有删除的问题 后来看到有人导了不一样的版本 xf
  • java求完数的三种方法

    package al 64 author zhangrichao 64 version 创建时间 xff1a 2019年1月6日 下午8 55 34 求完数 第一种方法 xff1a 减法方式 public class PerfectNumb
  • 用java实现快速排序算法

    第一种方法 xff1a xff08 从数组右边开始 xff09 1 选择一个比较值c xff0c 以数组的第一个为例 2 从右边开始查找比c小的值 xff0c 再从左边开始查找比c大的值 xff0c 进行互换 3 当左边和右边同时指向一个值
  • Spring MVC常用注解

    一 Spring MVC 常用注解 1 64 RequestMapping Spring MVC 通过 64 RequestMapping 注解将 URL 请求与业务方法进行映射 xff0c 在控制器的类定义处以及方法定义处都可以添加 64
  • 字符串通配符(递归)

    题目描述 问题描述 xff1a 在计算机中 xff0c 通配符一种特殊语法 xff0c 广泛应用于文件搜索 数据库 正则表达式等领域 现要求各位实现字符串通配符的算法 要求 xff1a 实现如下2个通配符 xff1a xff1a 匹配0个或
  • 数据结构 实验报告01

    一 实验目的和要求 完成尽可能多的数据排序 xff0c 并显示运行时间 二 实验环境 编译器 xff1a Vscode DevC 43 43 系统 xff1a Windows10 CPU xff1a i5 8265U 64 1 60GHz
  • eclipse中java代码自动补全设置

    下面介绍一个eclipse自动补全的设置1 在eclipse页面 xff0c 点击顶部的Window选项选择进入Preferences选项 xff1a 2 点击java gt Editor gt Content Assist选项 xff1a
  • Java两种方法去除字符串末尾的数字

    问题 xff1a 如何去除这个字符串中末尾的数字 xff1a sdf12 432fdsf gfdf32 xff1f 这个问题的解决关键是要先把字符串进行反转操作 方法一 xff1a public static String removeNu
  • The word 'jsp' is not correctly spelled. Eclipse 拼写检查出错处理办法

    The word 39 jsp 39 is not correctly spelled Eclipse 拼写检查出错处理办法 用Eclipse开发程序 xff0c 发现输入JSP时 xff0c 系统提示The word 39 jsp 39
  • prepareStatement与Statement的区别

    prepareStatement与Statement的区别 1 区别 xff1a stmt 61 conn CreateStatement resultSet rs 61 stmt executeQuery sql 上面是statement