zoukankan      html  css  js  c++  java
  • JDBC04----预编译语句介绍

     sql的拼接很麻烦,且容易出错,因此就可以使用预编译语句。

    接口java.sql.Statement有两个子接口:CallableStatement,PreparedStatement

    有两种类型的sql语句:

    1.静态sql

    在执行之前就知道了sql语句的形式。

    2.动态sql

    一. Statement接口的实现类

    1. PreparedStatement

    • PreparedStatement用于预编译模板SQL语句,在运行时接受SQL输入参数。eg:PreparedStatement ps=conn.preparedStatement(sql);
    • 在性能和代码灵活性上有显著的提高
    • PreparedStatement对象使用?作为占位符,即参数标记;eg:  select *from stu where id=?;  insert into stu value(?,?,?);
    • 使用setXXX(index,value)方法将值绑定到参数中,每个参数标记是其顺序位置引用,注意index从1开始;eg:ps.setInt(1,stu.getId());
    • PreparedStatement对象执行sql语句:executeQuery()、executeUpdate(),注意,他们没有参数; eg:ps.executeUpdate();

    2. 举例

    public Stu get(int id) {
            ResultSet resultSet=null;
            Connection connection=null;
            PreparedStatement pStatement=null;
            Stu student=new Stu();
            try {
                Class.forName(JDBCUtil.driverName);
                connection=JDBCUtil.getConnection();
                String sql="select *from stu where id=?";
                pStatement=connection.prepareStatement(sql);
                pStatement.setInt(1, id);//note这里的id时传入的,如果传入参数是student,就可以改成pStatement.setInt(1,student.getId())
                resultSet=pStatement.executeQuery();
                if(resultSet.next()) {
                    student.setId(resultSet.getInt("id"));
                    student.setName(resultSet.getString("name"));
                    student.setAge(resultSet.getInt("age"));
                    return student;
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                JDBCUtil.close(connection, pStatement, resultSet);
            }
            return null;
        }

    3. 如果没有使用预编译语句

    如果没有使用预编译语句的话,假设已经有一个静态的sql语句了,每一次查找的age不同,都会往预编池中写入一次数据。

    4. 如果使用预编译语句

    参数统一用?表示,这样预编译池中就不会多次写入数据了。---------(当很多人操作数据库时,这回很麻烦的)

    note: mysql不支持预编译池,oracle支持预编译池。

     

    6. 使用预编译可以防止SQL注入。

    (1)什么是SQL注入(note: 后面文章还会补充关于SQL注入以及如何防止SQL注入的知识!!!,这里只是先简单了解下)

    就是通过把SQL命令插入到WEB表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL语句。(说人话:就是一些错误的sql语句,导致了错误的sql语义被执行了)

    (2)SQL注入举例

    上面是一个用户登陆的代码,当用户名如上定义时,虽然表中没有这个用户,但是最终的结果会发现打印了登陆成功。打印出这一条sql语句:

    因此,看到拼接结果可以知道前面那个条件已经满足了,就不会管or后面的语句了:即name=‘’已经成立了。

    如果使用预编译,因为它执行的时候会把单引号转义。----也就是防止SQL注入的根源

     如果使用预编译:

     

    (3)为什么PrepareStaet就能防止注入

    是因为它把单引号转义了,变成了,这样一来,就无法截断SQL语句,进而无法拼接SQL语句,基本上没有办法注入了。

    二. JDBC调用输出参数存储过程----CallableStatement

    1. 创建一个存储过程

    测试下:

    2. 使用Java程序来实现调用

    public void call(){
            Connection connection=JDBCUtil.getConnection();
            CallableStatement cStatement;
            try {
                cStatement = connection.prepareCall("{call getName(?,?)}");
                cStatement.setInt(1, 2);
                cStatement.registerOutParameter(2, Types.VARCHAR);
                cStatement.execute();
                String name=cStatement.getString(2);
                System.out.println(name);
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }

     参考文献

    https://ke.qq.com/course/339214

  • 相关阅读:
    Python之路——内置函数
    Python之路——迭代器与生成器
    Python之路——函数
    Python之路——琐碎知识
    oracle 11g ocp 笔记(17)--rman高级功能
    oracle 11g ocp 笔记(16)--使用rman进行恢复
    oracle 11g ocp 笔记(15)--使用rman进行备份
    oracle 11g ocp 笔记(14)--数据库备份和恢复配置
    oracle 11g ocp 笔记(13)--子查询和集合运算符
    oracle 11g ocp 笔记(12)--sql关联
  • 原文地址:https://www.cnblogs.com/Hermioner/p/10234711.html
Copyright © 2011-2022 走看看