jdbc的使用(二)--结果集ResultSet、元数据、预编译PreparedStatement对象、批处理(batch)

1. 结果集ResultSet

1.1 结果集ResultSet的滚动特性

何为滚动?
如果结果集的光标,既可以向上移动,又可以向下移动就称之为可滚动的结果集;如果只能向下移动则称为不可滚动的结果集!

按照jdbc标准默认的结果集,不可滚动!但mysql并没有遵循jdbc的标准,mysql的默认结果集就是滚动的!

移动结果集ResultSet游标位置的方法:
按照jdbc标准,非滚动结果集只能调用next方法,滚动结果集可以调用所有方法,但mysql并没有遵循这一标准,mysql的默认结果集对以下所有的方法都支持。

  • (绝对移动)
    • void beforeFirst():把光标放到第一行的前面,这也是光标默认的位置;
    • void afterLast():把光标放到最后一行的后面;
    • boolean first():把光标放到第一行的位置上,返回值表示调控光标是否成功;
    • boolean last():把光标放到最后一行的位置上;
    • boolean absolute(int row):绝对位移,把光标移动到指定的行上;
  • (相对移动)
    • boolean previous():把光标向上挪一行;注意:必须先向下移,才能向上 移。
    • boolean next():把光标向下挪一行;
    • boolean relative(int row):相对位移,当row为正数时,表示向下移动row行,为负数时表示向上移动row行;

判断结果集位置的方法:
按照jdbc标准,不管是不是滚动结果都可以使用以下方法!

  • boolean isBeforeFirst():当前光标位置是否在第一行前面;
  • boolean isAfterLast():当前光标位置是否在最后一行的后面;
  • boolean isFirst():当前光标位置是否在第一行上;
  • boolean isLast():当前光标位置是否在最后一行上;
  • int getRow():返回当前光标所在行。

1.2 结果集ResultSet的敏感和可更新特性

结果集的特性有:

  • 是否可滚动
  • 是否敏感
  • 是否可更新

何为敏感?
数据库的更新会带动结果集的更新!
何为不敏感?–数据库厂商实现了
数据库的更新不会带动结果集的更新!

何为可更新?
结果集的变化会反向修改数据库中的记录
何为不可更新?
结果集的变化不会修改数据库中的记录

结果集的特性是什么时候确定的?(按照jdbc说的)
结果集是通过statement得到的
结果集特性是当使用Connection的createStatement方法时,就已经确定了Statement生成的结果集是什么特性!

补充: ResultSet的特性是他的爷爷确定的,而不是爸爸确定的!
ResultSet的爸爸—>Statement.executeQuery(sql)
ResultSet的爷爷—>Connection.createStatement()/createStatement(int,int)得到Statement

如何配置参数确定结果集的特性
默认方法con.createSttement():生成的结果集:不滚动、不敏感、不可更新!

如果想设置结果集的特性,可以调用该方法进行设置,con.createStatement(int,int):
Statement createStatement(int resultSetType, int resultSetConcurrency)

Publci interface rst{
Public static final int TYPE_FORWARD_ONLY=10;
}

Ret.TYPE_FORWARD_ONLY

1.3 ResulstSet给我们提供了一些静态参数!

第一个参数resultSetType:决定是否可滚动、是否敏感

  • ResultSet.TYPE_FORWARD_ONLY:不滚动结果集;
  • ResultSet.TYPE_SCROLL_INSENSITIVE:滚动结果集,但结果集数据不会再跟随数据库而变化;
  • ResultSet.TYPE_SCROLL_SENSITIVE:滚动结果集,但结果集数据会再跟随数据库而变化;(但没数据库厂商去实现)
    第二个参数:决定结果集是否可更新
  • CONCUR_READ_ONLY:结果集是只读的,不能通过修改结果集而反向影响数据库;
  • CONCUR_UPDATABLE:结果集是可更新的,对结果集的更新可以反向影响数据库。

2. 元数据

什么是元数据(metadata)?
数据本身的数据
Html里面有这样的一个元标签,元标签设置了html页面的编码

获取结果集元数据
有些数据我们可以通过结果集直接获得,而有些数据就要通过元数据来获得!
如何得到结果集元数据对象?
通过调用结果集的getMetaData()方法可以元数据对象,元数据对象的类型为ResultSetMetaData

通过元数据对象获得结果集的列数及列的名称
ResultSetMetaData

  • 获取结果集列数:int getColumnCount()
  • 获取指定列的列名:String getColumnName(int colIndex)
    例子:假如我们只有一个结果集对象,但不知道结果集中有多少条记录及列的个数和名称,现在让我们把结果集遍历出来!
    public static void main(String[] args) throws Exception {
        //加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //获得连接
        Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/vip03test01",
                "root", "123456");
        //通过元数据来遍历表
        Statement stmt = con.createStatement();
        //执行查询
        ResultSet rst = stmt.executeQuery("select * from stu");
        //得到结果集的元数据
        ResultSetMetaData metaData = rst.getMetaData();
        //列数
        int colCnt = metaData.getColumnCount();
        //把表的字段名称打出来
        for(int i=1;i<=colCnt;i++){
            String columnName = metaData.getColumnName(i);
            System.out.print(columnName+"\t");
        }
        System.out.println();
        while(rst.next()){ //控制行,控制游标的移动
            for(int i=1;i<=colCnt;i++){//控制列
                Object col = rst.getObject(i);
                System.out.print(col+"\t");
            }
            System.out.println();
        }
    }

3. 预编译PreparedStatement对象

3.1 PreparedStatement是什么?

PreparedStatement叫预编译声明!可以使用PreparedStatement来替换Statement。

PreparedStatement和Statement的关系
PreparedStatement是Statement接口的子接口。

PreparedStatement的优势:

  1. 防SQL攻击;
    防止SQL攻击的手段有哪些?
    1.1 使用PreparedStatement。(推荐使用)
    1.2 过滤用户输入的数据中是否包含非法字符;(不允许出现单引号)
    1.3 分步交验!先使用用户名来查询用户,如果查找到了,再比较密码;
  2. 提高代码的可读性、可维护性;
  3. 提高效率! – (预编译声明,他会把sql语句编译成一个sql模板,存到数据库中去。这个sql模板类似于一个函数的东西。)

3.2 PreparedStatement的用法:

  1. 通过调用Connection的PreparedStatement prepareStatement(String sql)方法得到PreparedStatement对象pstmt;模板 sql语句中的参数用?代替
  2. 调用pstmt的setXxx()系列方法sql模板中的?赋值!
  3. 调用pstmt的executeUpdate()或executeQuery(),但它的方法都没有参数。
    public static void main(String[] args) throws Exception{
        //获得连接
        Connection con = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/vip03test01?useServerPrepStmts=true&cachePrepStmts=true", "root", "123456");
        System.out.println(con);//com.mysql.jdbc.JDBC4Connection@446cdf90


      String sql = "select * from user where username=? and password = ?";//用?代替参数值  sql模板

        //执行查询操作
        //PrepareStatement(避免sql攻击)
        PreparedStatement pstmt = con.prepareStatement(sql);//prepareStatement执行的sql语句跟Statement执行的sql语句是不一样的
        //设置参数,通过pstmt
        pstmt.setString(1,"huangchenglong");
        pstmt.setString(2,"1234");


        //执行pstmt
        ResultSet resultSet = pstmt.executeQuery();
        
    }

3.3 预处理PreparedStatement的原理

首先说普通的Statemen的执行过程:
1、 把sql语句发送给数据库服务器
2、 数据库服务器对发送过来的sql语句进行语法校验
3、 对sql语句进行编译
4、 执行sql语句
如果多次发送sql语句,每一次都会执行上面的4步流程!

再来说PreparedStatement的执行流程:
1、 把sql语句(模板)发送给数据库服务器
2、 对sql语句(模板)进行语法校验
3、 对sql语句(模板)进行编译。(编译之后的东西就像函数)(数据库会把该“函数”保存,供以后反复使用)
4、 把pstmt中设置的参数传递给第三步编译之后的sql语句,并执行。(就像调用函数)
如果再次调用该预编译执行,则不会重复以上1/2/3步,只会执行第四步!

1.4 配置mysql的预编译功能

因为mysql4.0之后,预编译的功能默认是关闭的,所以我们需要手动打开mysql的预编译功能才能使用!否则,mysql就不能真正实现预编译的功能!

如何打开mysql的预编译功能呢?其实也很简单!
只需要在jdbc的url后添加两个参数即可!
useServerPrepStmts=true
cachePrepStmts=true

Connection con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb1? useServerPrepStmts=true& cachePrepStmts=true",
"root", "1234");

4. JDBC的批处理(batch)

什么是批处理()
所谓的批处理就是一批一批的处理,而不是一个一个的处理!这里的批指的就是集合。
之前的sql语句是一条一条的发送,而如果是批处理就可以一次性发送一批sql语句给数据库服务器执行。

批处理只针对更新(增、删、改)语句,批处理没有查询什么事儿!
代码演示(关键代码:stmt.addBatch(sql))

注意事项
开启批处理:在url后面添加参数:rewriteBatchedStatements=true

    public void method() throws Exception{
        Connection connection = JdbcUtils03.getConnection();
        String sql = "insert into student values(?,?)";
        PreparedStatement pstmt = connection.prepareStatement(sql);

        for(int i=3;i<103;i++){
            pstmt.setInt(1,i);   //id
            pstmt.setString(2,"aa"+i);  //name
            pstmt.addBatch();//添加批
        }

        pstmt.executeBatch();//执行批处理
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值