JDBC核心类库

13 篇文章 1 订阅

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 漏洞实例这里写图片描述
    • 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();
        }

    }

}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 使用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();
        }

    }

}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

statement 和preparedStatement 区别

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

预处理的原理

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值