在学习JDBC的时候碰到一个问题。获取向数据库发送sql语句的statement对象有两种类似的接口这两个接口没有本质上的区别。都是通过对象调用executeQuery方法来执行SQL语句。说是CreateStatement和PrepareStatement的区别,但其实说的就是Statement和PrepareStatement的区别。
第一点:
conn.=JdbcUtils.getConnection()
stmt=conn.CreateStatement();
resultSet rs=stmt.executeQuery(sql);
上面是statement的用法
============================
下面是PrepareStatement的用法
conn.=JdbcUtils.getConnection()
ptmt=conn.PreparedStatement(sql);
resultSet rs=ptmt.executeQuery();
================================
Statement 是PreparedStatement的父类
还有就是sql放置的位置不同 。
学习背景Jdbc学习01博客篇中有数据jdbcdemo库中有users表。有id,name,password,email,birthday等字段。
这是使用conn.createStatement()方法创建的st对象,再通过它向数据发送执行的插入语句sql。
//数据库添加数据测试
@Test
public void insert() throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
st= conn.createStatement();
String sql="insert into users(id,name,password,email,birthday) values(4,'liayun','123321','liayun@163.com','1992-10-06')";
int num=st.executeUpdate(sql);
if (num>0){
System.out.println("插入成功!!!");
}
conn.close();
st.close();
}
}
下面是使用PrepareStatement方法创建了pt对象,再通过它向数据发送执行的插入语句sql。
//更新数据测试
@Test
public void update() throws SQLException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql="update users set name=? where id =?";
ps = conn.prepareStatement(sql);
ps.setString(1,"小豆包");
ps.setInt(2,4);
int i = ps.executeUpdate();
if (i>0){
System.out.println("更新成功!!!");
}
}
}
通过两端代码块就能看出来了。PrepareStatement跟Statement的主要区别就是把上面sql语句中的变量抽出来了。这就是我要说的第一大优点,PrepareStatement可以提高代码的可读性。也许你刚开始写SQL语句觉得第一种stament对象执行的SQL明显简单且一句话就能了事何必麻烦再去抽取赋值。但是我们得考虑以后啊!当你的数据库表字段越来越多SQL语句越来越复杂一个表几十个字段的时候这时你想想的如果用第一种SQL语句的写法会显得很臃肿没有可读性,不光别人会看吐你自己也会看吐的。。。
下面说说第二点优点。ParperStatement提高了代码的灵活性和执行效率。
PrepareStatement接口是Statement接口的子接口,他继承了Statement接口的所有功能。它主要是拿来解决我们使用Statement对象多次执行同一个SQL语句的效率问题的。ParperStatement接口的机制是在数据库支持预编译的情况下预先将SQL语句编译,当多次执行这条SQL语句时,可以直接执行编译好的SQL语句,这样就大大提高了程序的灵活性和执行效率。
最后但也是最重要的一个大大的比Statement好的优点,那就是安全!
我给你一行代码参考一下
String sql = "select * from user where username= '"+username+"' and userpwd='"+password+"'";
st = conn.createStatement();
rs = st.executeUpdate(sql);
这是验证用户名密码的,对吧。但要是我们把'or '1' = 1'当作密码传进去,你猜猜会发生什么。
select * from user where username = 'user' and userpwd = '' or '1' = '1';
发现了吧!这是个永真式,因为1永远等于1。所以不管怎样都能获取到权限。这还不是最坏的,你再看!
依旧是这行代码。这次我们把'or '1' = 1';drop table book;当成密码传进去。这次直接把表给删了。但是,你如果用PrepareStatement的话就不会出现这种问题。这就是我们常说的sql防注入的问题。你传入的这些数据根本不会跟原来的数据有任何的交集,也不会发生这些问题。
String sql = "select * from user where username= '"+username+"' and userpwd='"+password+"'";
st = conn.createStatement();
rs = st.executeUpdate(sql);
你看看如果使用的是PrepareStatement的话就是这样了,相对于CreateStatement减少了恶意数据的写入。
String sql = "select * from user where username=? and userpwd=?";
pst=conn.prepareStatement(sql);
pst.setString(1,username);
pst.setString(2,password);
rs = ps.executeQuery();
转载请说明转载来源https://blog.csdn.net/weixin_41092717/article/details/82853704