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()来获取查询语句的结果
- execute(String sql) 使用这方式,可以输入任何sql语句,但是由于他的返回值只是布尔值,我们不能清楚到底操作了几行,
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漏洞代码演示
- 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()方法。为参数赋值
- 调用控参数的查询方法
- 创建sql模板
- 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语法,也不用编译,直接执行。