JDBC预编译学习笔记

JDBC预编译学习笔记

使用JDBC中的statement对象执行SQL语句时,由于SQL语句可以通过字符串进行拼接,因此会出现SQL注入问题,是不安全的。

例如:

//定义SQL 
String sql = "select * from user where userName='"+userName+"' and password="+password;

输入的用户名与密码匹配才能获得用户的信息,但是如果把[or 1 = 1]作为password传入进来,就成了

String sql = "select * from user where userName='随意用户名' and password='' or 1=1";

因为 1=1 成立,where条件一定为真,所以密码错误也可以通过验证。

使用PreparedStatement

​ 预编译语句PreparedStatement 是java.sql中的一个接口,它是Statement的子接口。使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入。

预编译的使用:

​ 1.在定义sql语句的时候,待填入的参数用 ? 占位。例如下面的代码

//定义SQL 
String sql = "select * from student where sname=? and sid=?";

​ 2.创建 PreparedStatement 预编译对象 ,并把sql语句传入。

//预编译sql,conn是Connection对象
PreparedStatement ps = conn.prepareStatement(sql);

​ 3.给占位符 ? 设置参数,方法的参数一代表占位符的位置(从1开始),参数二代表要设置的值,使用的setXX()方法与数值类型有关,字符串就是setString(index,str).

ps.setString(1, "张三");
ps.setInt(2, 9);
// sql语句设置成了 "select * from student where sname='张三' and sid=9";

​ 4.执行sql语句,第二步已经把sql语句与preparedStatement绑定,所以此时无需再把sql语句作为参数传入executeQuery。

//执行SQL获取结果集
ResultSet rs = ps.executeQuery();

​ 一旦设置了给定语句的参数值,其值将一直保留,直到被设置为新值或者调用clearParameters()方法清除它为止。

​ 在使用参数化查询的情况下,数据库系统不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。

预编译增删改封装
/**
 * 数据库连接工具类
 */
public class DBUtil {
	
	//数据库驱动
	private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
	//数据库连接参数,staff_manager是数据库名称
	private static final String URL = "jdbc:mysql://localhost:3306/staff_manager?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai";
	//登录数据库的用户名
	private static final String USER = "root";
	//数据库登录密码
	private static final String PASSWORD = "123456";
	
	private static Connection conn =null;
	
	//注册驱动
	static {
		try {
			//反射
			Class.forName(DRIVER);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取连接对象
	 */
	public static Connection newInstance() {
		
			 try {
				conn = DriverManager.getConnection(URL, USER, PASSWORD);
			} catch (SQLException e) {
				e.printStackTrace();
			}
		
		return conn;
	}
	
	/**
	 * 使用预编译对象的增删改通用方法
	 * @param sql  预编译sql语句
	 * @param objects  给占位符设置参数
	 * @return
	 */
	public static int precurdMethod(String sql,Object...objects) {
		//PreparedStatement类有预编译sql语句的方法,变量定义在上面供下面各个代码块使用
		PreparedStatement ps = null;
		
		//创建连接
		newInstance();
		
		//创建预编译对象,并连接sql语句
		try {
			ps = conn.prepareStatement(sql);
			//先判断sql语句是否有占位符要设置
			if(objects != null) {
				//第二个参数不为null,则说明需要设置sql语句的占位符
				for(int i=0;i<objects.length;i++) {
					//每次循环就给一个占位符 ? 设置参数,注意占位符下标是从1开始
					ps.setObject(i+1, objects[i]);
				}
			}
			
			//执行设置完占位符后的sql,返回值是sql语句影响到数据库的行数
			int result = ps.executeUpdate();
			
			return result;
		} catch (SQLException e) {
			e.printStackTrace();
			
		}finally {
			//关闭连接
			close(conn,ps,null);
		}
		return 0;		
		
	}
	
	
	/**
	 * 关闭连接对象
	 * @param conn  连接数据库对象
	 * @param sta	预编译sql语句对象
	 * @param rs	结果集对象
	 */
	public static void close(Connection conn,Statement sta,ResultSet rs) {
			try {
				if(rs != null){
					rs.close();
				}
				if(sta != null) {
					sta.close();
				}
				if(conn != null) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值