Java Web 学习之JDBC 基础(篇2)

本文探讨了SQL注入的危害,并通过实例展示了其可能造成的安全风险。PreparedStatement作为解决方案,通过预编译SQL语句和参数化查询,有效防止SQL注入,提高了代码的安全性和执行效率。此外,还介绍了使用PreparedStatement进行批量处理的方法,以提升数据库操作性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

篇1 介绍了使用JDBC 连接数据库及部分API 实现sql 查询,及数据库资源的回收,本篇主要是围绕 PrepaeredStatement对象的使用及Sql注入相关:

    1.Sql 注入:

         sql注入是比较常见的网络攻击形式,它利用现有的程序漏洞,将恶意的Sql命令注入后台数据库,最终达到欺骗服务器并实现攻击者的意图,在程序运行过程中,Sql注入会造成数据库信息泄露,网页被篡改,网站被挂木马等问题,

 如接下来的两个Sql 语句:

     Select *  from  用户表 where name=用户输入的用户名 AND password=用户输入的密码;

     Select * from 用户表 Where name="用户输入的用户名"  AND password=12345 or 1=1;

    此时,上述查询已基本失效,无论密码对错,用户均可以成功登陆,使得程序存在重大的安全隐患,这就是Sql注入 的一个具体场景。

    篇1已经介绍过,Satement 对象可以通过3种方法向数据库发送Sql 语句,而这3种方法均是通过 传递字符类型的Sql 语句作为参数来实现的,由此可见,使用Statement 类会存在 SQL 注入的问题。

  2.PreparedStatement 与Statement  对比:

     PreparedStatement 是用来执行Sql 查询语句的API 之一,主要用来执行参数化的操作,PrepareStatement 对象可以对Sql 语句进行预编译,这可以有效的避免Sql 注入引发的问题,同时也提升了代码的可维护性和可读性:

   它有一下优点:

     1.PrepareStatement 能够执行参数化的Sql语句:

     由于PrepareStatement 能够执行带参数化的Sql 语句,因此开发人员可以通过修改参数来反复调用同一个SQL 语句,这样可以避免反复书写相同的SQL 语句的繁琐。

      参数化Sql 语句:

      select count(1)  from t_student where name=? and password = ?; 

      

    其中,“?” 是参数的占位符,程序可以通过传入不同的sid 值完成参数化查询   

2. PrepareStatement 比Statement 效率更高:

    使用PrepareStatement 时,数据库系统会对Sql语句进行预编译处理,执行计划同样会被缓存起来,这条预编译的SQL 语句能在将来的查询中重用,这样一来,它比Statement 对象生成的查询速度更快,性能更好,为了减少数据库的负载,在实际开发过程中一般使用PrepareStatement。

3.PrepareStatement 可以防止SQL 注入攻击

    使用PrepareStatement 的参数化操作可以阻止大部分的Sql注入,在使用参数化查询的情况下,数据库系统不会将参数的内容视为SQL 指令的一部分来处理,而是在数据库完成SQL 指令的编译后,才套用参数执行。

    使用PraparedStatement  对象通过executeUpate() 方法来实现·对数据库的写入,通过executeQuery() 方法实现对数据库的查询,使用PrepareStatement对象操作数据库的步骤与使用Statement 对象类似:

	//解决sql注入的操作:
	private static boolean login2(String name, String password) {
		Connection conn = null;
		PreparedStatement prst = null;
		ResultSet    rs = null;
		try {
			conn = DBUtils.getConnection();
			//获取预处理的执行对象:
			//好处:1.解决sql注入隐患问题  2.效率高
			//?:代表占位符
			String sql = "select count(1) from t_student where name=? and password=?";
			prst = conn.prepareStatement(sql);
			//-------给占位符赋值-------
			prst.setString(1, name);  //对应第一个?,参数下标从1开始
			prst.setString(2, password); //对应第二个?
		    rs = prst.executeQuery();
		    if(rs.next()){
			   int result = rs.getInt(1); //获取第一个字段的值
			   return result>0; //如果大于0则为true
		    }
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBUtils.closeAll(rs,prst,conn);
		}
		
		return false;
	}

4.使用PrepareStatement 对象实现批量处理:

    在实际的开发过程中,有时需要向数据库送多条语句相同,但参数不同的SQL 语句,这是需要写上多条SQL 语句

   为了避免重复发生相同的SQL语句,提升执行效率,在实际的开发过程中常采用PrepareStatement对象的批处理机制:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class DBTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {

        //加载并注册数据库驱动
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/renpengcheng";
        String username = "root";
        String password = "123456";

        //获取数据库连接
        Connection connection = DriverManager.getConnection(url, username, password);
        //书写Sql语句
        String sql = "insert into student (sname,age,course)  values (?,?,?)";
        //获取执行对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i <= 2; i++) {
            preparedStatement.setString(1, "name" + i);
            preparedStatement.setString(2, "22");
            preparedStatement.setString(3, "java");

            //添加进批
            preparedStatement.addBatch();
            //设置条件,当i对10取余为0时,先执行一次语句,然后将批清除
            if (i % 10 == 0) {
                preparedStatement.executeBatch();
                preparedStatement.clearBatch();
            }
        }


        //将批中剩余的语句执行完毕
        preparedStatement.executeBatch();
        //关闭资源
        preparedStatement.close();
        connection.close();

    }
}

 

 

 

 

 

 

 

 

 

     

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焱宣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值