• JavaWeb学习(七): Statement 与 PreparedStatement 的区别 :


    前言:

    两者由哪个类产生?

    Connection 产生 Statement 对象 : createStatement()
    Connection 产生 PreparedStatement 对象 : prepareStatement()
    Connection 产生 CallableStatement   对象 : prepareCall()
    

    两者之间的关系:

    public interface PreparedStatement extends Statement
    由此可知: PreparedStatement 是Statement 的一个子接口
    所以   : Statement有的东西PreparedStatement 也有,甚至子类还比父类多很多东西 
    

    两者是通过怎么的方式操作数据库的?

    Statement :

    增删改 :executeUpdate()
    查询  :  executeQuery()   ---  返回的是一个结果集(ResultSet)
    

    PreparedStatement:

    增删改  : executeUpdate()
    查询   :  executeQuery() ---  返回的是一个结果集(ResultSet)
    赋值操作:setXxx();        ---   相对于 Statement 强大的地方
    

    两者在使用时的区别(具体看代码,更好理解):

    Statement:

    1、SQL 语句
    2、executeUpdate(sql)
    

    PareparedStatement:

    sql(可以存在占位符?)
    在创建PreparedStatement 对象时,将sql预编译 prepareStatement(sql);
    setXxx()替换占位符  (两个参数: 位置,值)
    executeUpdate(); -- 由于已经预编译过,所以不用再进行重复编译
    

    PareparedStatement 的优势:

    1、编码更加简便(直接用 ?代替,避免了字符串的拼接)
    2、提高性能(预编译,避免了重复编译,提高了性能)
    3、安全(可以有效防止 sql 注入)
    
    sql注入: 将用户输入的内容 和开发人员的SQL语句混为一体
    
    stmt : 存在被注入的风险
    (例如输入 用户名:任意值 ' or 1 = 1 --
                密码:任意值
    )
    分析:
    select count(*) from login where uname='任意值' or 1=1 --' and upwd = '任意值’;
    (SQL语句中 -- 起注释的作用)
    select count(*) from login where uname='任意值' or 1=1;
    select count(*) from login;
    
    pstmt : 有效防止 sql 注入(推荐使用)
    select count(*) from login where uname=? and upwd = ?;
    (没有符号跟 ?配对)
    

    代码进行区别:

    Statement:

    package controlSql;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class SqlQuery {
    	private static final String URL = "jdbc:mysql://localhost:3306/sqltest";
    	private static final String User = "root";
    	private static final String Pwd = "root";
    	
    	// 查询操作
    	public static void query() {
    		Connection connection = null;
    		Statement stamt = null;
    		ResultSet rs = null;
    		try {
    			Class.forName("com.mysql.jdbc.Driver");
    
    			connection = DriverManager.getConnection(URL, User, Pwd);
    			stamt = connection.createStatement();
    			String sql = "select sno,sname from s";
    			// 查询操作 : 返回结果集
    			rs = stamt.executeQuery(sql);
    			// 指针不为空一直向下走(也可以向上走 -- rs.previous())
    			while (rs.next()) {
    				// 通过  getXxx 方法获得 数据库中每个字段的信息 
    				String sno = rs.getString("sno");
    				String sname = rs.getString("sname");
    				System.out.println(sno + "--" + sname);
    			}
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				// 用完后记得关闭,最后开的先关闭,最先开的最后关闭
    				rs.close();
    				stamt.close();
    				connection.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	// 更新操作
    	
    	public static void update() {
    		Connection connection = null;
    		Statement stamt = null;
    		ResultSet rs = null;
    		try {
    			Class.forName("com.mysql.jdbc.Driver");
    
    			connection = DriverManager.getConnection(URL, User, Pwd);
    			stamt = connection.createStatement();
    			// 括号里面的字段值需要用 单引号 '',较为复杂时要用到字符串的拼接
    			String sql = "insert into s values ('1006','sd','13')";
    			
    			int cnt = stamt.executeUpdate(sql);
    			
    			if(cnt > 0) System.out.print("操作成功!");
    			else System.out.print("操作失败!");
    			
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				// 用完后记得关闭,最后开的先关闭,最先开的最后关闭
    				stamt.close();
    				connection.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	public static void main(String[] args) {
    		update();
    //		query();
    	}
    }
    
    

    PreparedStatement:

    package controlSql;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class PreparedStatementExample {
    	private static final String URL = "jdbc:mysql://localhost:3306/sqltest";
    	private static final String User = "root";
    	private static final String Pwd = "root";
    
    	public static void query() {
    		Connection connection = null;
    		PreparedStatement stamt = null;
    		ResultSet rs = null;
    		try {
    			Class.forName("com.mysql.jdbc.Driver");
    
    			connection = DriverManager.getConnection(URL, User, Pwd);
    			// 查询操作(实现模糊查询)
    			String sql = "select * from s where sname like ? ";
    			stamt = connection.prepareStatement(sql);			
    			stamt.setString(1, "%s%");
    			rs = stamt.executeQuery();
    			while (rs.next()) {
    				// 通过  getXxx 方法获得 数据库中每个字段的信息 
    				String sno = rs.getString("sno");
    				String sname = rs.getString("sname");
    				System.out.println(sno + "--" + sname);
    			}
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				// 用完后记得关闭,最后开的先关闭,最先开的最后关闭
    				rs.close();
    				stamt.close();
    				connection.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	public static void update() {
    		Connection connection = null;
    		PreparedStatement stamt = null;
    		try {
    			Class.forName("com.mysql.jdbc.Driver");
    
    			connection = DriverManager.getConnection(URL, User, Pwd);
    			// 插入操作
    			String sql = "insert into s values (?,?,?)";
    			// 预编译
    			stamt = connection.prepareStatement(sql);
    			// 按照位置进行插入
    			stamt.setString(1, "1005");
    			stamt.setString(2, "wu");
    			stamt.setString(3, "23");
    			
    			int cnt = stamt.executeUpdate();
    			
    			if(cnt > 0) System.out.print("操作成功!");
    			else System.out.print("操作失败!");
    			
    			
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				// 用完后记得关闭,最后开的先关闭,最先开的最后关闭
    				stamt.close();
    				connection.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	public static void main(String[] args) {
    //		query();
    		update();
    	}
    }
    
    
  • 相关阅读:

    守护线程
    下载图片
    多线程
    self的作用
    设置项目地址环境
    对象 类
    ValueError: urls must start with a leading slash
    mock挡板接口开发
    K&R——第五章 指针与数组
  • 原文地址:https://www.cnblogs.com/prjruckyone/p/12503410.html
Copyright © 2020-2023  润新知