1. 继承关系
首先来看看它们之间的联系,两者都是接口,都是由Connection接口创建得到的,而PreparedStatement呢,它是Statement的子接口,是继承于Statement接口而得到的。
2. PreparedStatement和Statement的区别
2.1 从代码的可读性和可维护性来说
PreparedStatement在执行sql语句时可以包含动态参数占位符“?”,在执行时可以为占位符“?”动态设置参数值,而Statement不支持占位符“?”替换变量,只能在sql中拼接参数。
所以在代码的可读性以及可维护性上,PreparedStatement接口大大提高了代码的可读性和可维护性。
2.2 PreparedStatement会尽最大可能提高性能
我们知道sql语句的在数据库中执行都是需要DBMS编译的,而PreparedStatement会预编译sql语句,因此当多次执行时,只需DBMS运行sql语句,而不必再编译。而Statement没有预处理,每次都要重新编译,所以当多次执行这条sql语句时,PreparedStatement效率会大大的提高。
2.3 PreparedStatement可以防止sql注入,极大地提高了安全性
PreparedStatement可防止sql注入。sql注入情况如下所示:
如果有一条登录的sql语句
"select * from user where name = 'zhangsan' and password = 123456";
Statement的sql语句是这样写的
"select * from user where name = '" + username + "' and password ='" + password + "'";
这样我们就发现输入用户名:'or'1=1'#,密码随意输入时。
Statement会将这个和sql语句做字符串连接到一起执行,变成了
select * from user where name = ''or' 1=1'# and `password` =123456
,而#这个字符后面的在MySQL数据库中会把它当作注释,所以sql就变成了
select * from user where name = ''or'1=1'
,这样的sql语句执行会导致永远都可登录成功。而PreparedStatement是将'or'1=1'# 作为一个字符串赋值给占位符“?”赋值,作为"用户名"字段的对应值,显然这样SQL注入就可以避免了。
2.4 批处理性能
以数据量大小为标准选择Statement与PrepareStatement时的标准:
1)量比较小,二者皆差别不大。
2)量比较多,在PreparedStatement预编译空间范围之内,选择PreparedStatement,因为其只预编译一次sql语句。
3)量特别大,使用Statement,因为PrepareStatement的预编译空间有限,当数据量特别大时,会发生异常。
使用PreparedStatement代码演示:
在批处理过程中包含的sql语句的主干部分(sql语句)必须相同,改变的只是参数,因此编译一次sql语句即可,极大提高性能,但其主干必须相同则影响了灵活性。
public static void main(String[] args) {
Connection conn = null;
Statement stat = null;
PreparedStatement ps = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///mydb5","root","admin");
//开始事务
conn.setAutoCommit(false);
String sql = "insert into tb_batch values (null,?)";
ps = conn.prepareStatement(sql);
for(int i=2000;i<3000;i++){
ps.setString(1, "tong"+i);
ps.addBatch();
}
ps.executeBatch();
//提交事务
conn.commit();
} catch (Exception e) {
e.printStackTrace();
}finally{
JDBCutils.closeResou(conn, ps, null);
}
}
使用Statement代码演示:
可以包含结构不同的sql语句,灵活性得到提高,但没有预编译机制, 效率低下;并且你会发现发送的sql语句主干部分相同,只是参数不同, 但是主干部分每次都需要重复写入,极为麻烦。
Connection conn = null;
Statement stat = null;
//注册驱动和连接数据库
conn = JDBCutils.getConn();
try {
stat = conn.createStatement();
stat.addBatch("drop database if exists mydb5");
stat.addBatch("create database mydb5");
stat.addBatch("insert into tb_batch values(null,'a')");
stat.addBatch("insert into tb_batch values(null,'bbb')");
stat.addBatch("insert into tb_batch values(null,'cccccc')");
stat.executeBatch();
} catch (Exception e) {
e.printStackTrace();
}finally{
JDBCutils.closeResou(conn, stat, null);
}
————————————————
版权声明:本文为CSDN博主「初夏0811」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37899908/article/details/113418900