jdbc核心类库

jdbc核心类库有

  • DriverManager
  • Connection
  • Statement
  • ResultSet

DriverManager的作用

  • 注册驱动:可以让JDBC知道使用的是哪个驱动
  • 获取Connection连接对象:如果能获取到Connection对象,说明已经成功连接到了

Connection 的作用

  • 用来获取发送器对象Statement,这样数据库就可以发送sql语句了

Statement

  • 常用的方法
    • executeUpdate(String sql)执行更新操作,insert ,update,delete等,其实也可以执行create table , alter table , drop table 等操作,但是不建议使用
    • executeQuery(String sql)执行sql的查询语句,返回值是一个结果集对象ResultSet
  • 不常用的方法,但是要知道
    • execute(String sql) 使用这方式,可以输入任何sql语句,但是由于他的返回值只是布尔值,我们不能清楚到底操作了几行,
      • 所以这个方法一般要配合getUpdateCount()方法来获取影响的行数
      • 如果执行的是查询操作还需要,通过Result的getResultSet()来获取查询语句的结果

ResultSet

  • 就是一张二维的表格,它内部有一个“行光标”,光标默认 的位置在第一行的上面
  • 常用的方法
    • next() 光标向下移动一行
    • getxxx(String 列名) 获取指定列的值
  • 不常用的方法
    • beforeFirst()将光标移动到第一行的前面。也就是默认的起始位置。
    • afterLast()将光标移动到最后一行的后面
    • first()将光标移动到第一行的位置
    • last()将光标移动到最后一行的位置
    • isBeforeFirst()当前光标是否在第一行的前面位置
    • isAfterLast()当前光标是否在最后一行的后面
    • isFirst()当前的光标是否在第一行
    • isLast()当前的光标是否在最后一行
    • previous()当前的光标位置向上移动一行
    • relative(int row):相对位移,当row为正数 的时候,表示向下移动row行,为负数时,表示向上移动row行
    • absolute(int row)将光标移动到指定的位置上
    • int getRow() 返回当前所有的光标行,一半用来获取数据的行数。

JDBC结果集的特性

  • 方法:
    Statement createStatement(int resultSetType,
    int resultSetConcurrency)
  • 参数:

    • 第一个参数
      • ResultSet.TYPE_FORWARD_ONLY:不滚动结果集;
      • ResultSet.TYPE_SCROLL_INSENSITIVE:滚动结果集,但结果集数据不会再跟随数据库而变化;
      • ResultSet.TYPE_SCROLL_SENSITIVE:滚动结果集,但结果集数据不会再跟随数据库而变化;(
        没有数据库驱动会支持它! )
    • 第二个参数
      • CONCUR_READ_ONLY:结果集是只读的,不能通过修改结果集而反向影响数据库;
      • CONCUR_UPDATABLE:结果集是可更新的,对结果集的更新可以反向影响数据库。
  • 是否滚动

    • 如果结果集不可滚动,那么只能使用next()方法来移动行标,但是判断行标位置的方法还是可以使用的。
    • 不可滚动禁用的方法:
      • beforeFirst()
      • first()
      • last()
      • afterLast()
      • previous()
      • relative()
  • 是否更新:结果集改变,数据库也改变
  • 是否敏感:数据库改变,结果集合也改变

==注意==
使用Connection.createStatement()方法创建的结果结合是不滚动,不敏感,不更新

PreparedStatement的用法

  • PrepareStatement 是Statement 的一个子接口,它更加强大 ,能够防止sql攻击
  • 提高代码的可维护性,可读性
  • 提高效率
  • Statement 漏洞实例jdbc核心类库_第1张图片
    • sql漏洞代码演示


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.Test;

public class Demo2 {
    /**
     * 测 是sql漏洞
     * @author lien
     * @throws SQLException 
     * */
    public boolean Bug(String username , String password) throws SQLException{
        /*
         * 四大参数
         * DriverClassName  com.mysql.jdbc.Driver
         * url  jdbc:mysql://localhost:3306/mydatabase1
         * user root
         * mypassword root
         * */
        String url = "jdbc:mysql://localhost:3306/mydatabase1";
        String user = "root";
        String mypassword = "root";

//      对象引用声明
        Connection con = null;
        Statement state = null;
        ResultSet query = null;
        //加载驱动类
        try {
            Class.forName("com.mysql.jdbc.Driver");
//          获得连接对象
            con = DriverManager.getConnection(url, user, mypassword);
//          获得发送器对象
            state = con.createStatement();
            //发送查询语句
            String sql = "select * from teacher where name='"+username + "' and age='"+password +"'";
            System.out.println(sql);
            //获得结果集合对象
            query = state.executeQuery(sql);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return query.next();


    }
    @Test
    public void test(){
        try {
            /*
             * 这里写了一个假条建,肯定是a=a肯定成立,那么就算name属性验证了不正确,但是结果还是ture
             * select * from teacher where name='a' or 'a'='a' and age='66' or '1'='1'
             */

            boolean bug = this.Bug("a' or 'a'='a", "66' or '1'='1");
            System.out.println(bug);
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

}
  • 使用PreparedStatement解决步骤
    • 创建sql模板
      • 参数使用?代替:例如:”select * from teacher where name=? and age=?”
      • 通过模板获得发送器对象:pst = con.prepareStatement(sqlpattern);
      • 调用发送器pst的setxxx()方法。为参数赋值
      • 调用控参数的查询方法


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

import org.junit.Test;

public class Demo2 {
    /**
     * 测 是sql漏洞
     * @author lien
     * @throws SQLException 
     * */
    public boolean Bug(String username , int password) throws SQLException{
        /*
         * 四大参数
         * DriverClassName  com.mysql.jdbc.Driver
         * url  jdbc:mysql://localhost:3306/mydatabase1
         * user root
         * mypassword root
         * */
        String url = "jdbc:mysql://localhost:3306/mydatabase1";
        String user = "root";
        String mypassword = "root";

//      对象引用声明
        Connection con = null;
        PreparedStatement pst = null;
        ResultSet query = null;
        //加载驱动类
        try {
            Class.forName("com.mysql.jdbc.Driver");
//          获得连接对象
            con = DriverManager.getConnection(url, user, mypassword);
//          sql模板,参数的地方使用?代替
            String sqlpattern = "select * from teacher where name=? and age=?";
//          获得发送器对象
            pst = con.prepareStatement(sqlpattern);
            //为参数赋值
            pst.setString(1, username);
            pst.setInt(2, password);

            //调用查询方法
            query = pst.executeQuery();


        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return query.next();


    }
    @Test
    public void test(){
        try {

            boolean bug = this.Bug("小明", 76);
            System.out.println(bug);
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

}

statement 和preparedStatement 区别

  • PreparedStatement继承了Statement(parparedStatement是statement的一个子接口)
  • PreparedStatement可以写动态参数化的查询
  • PreparedStatement比 Statement 更快
  • PreparedStatement可以防止SQL注入式攻击

预处理的原理

  • 服务器的工作
    • 校验sql语法的正确性
    • 编译:一个与函数相似的东西
    • 执行:调用函数
  • PreparedStatement
    • 前提:连接的数据库必须支持预处理
    • 每个preparedstatement 都和sql模板绑定在一起,先把sql模板给数据库,数据库先进行校验,在进行编译,此时只是把参数传递过去而已
    • 若二次执行,就不需要再次校验sql语法,也不用编译,直接执行。

你可能感兴趣的:(jdbc,jdbc,数据库)