首页 > 其他分享 >ResultSet详解

ResultSet详解

时间:2023-04-03 10:02:00浏览次数:39  
标签:调用 对象 ResultSet 游标 详解 移动 方法

ResultSet类型

ResultSet对象的类型主要体现在两个方面:

(1)游标可操作的方式。

(2)ResultSet对象的修改对数据库的影响。

后者称为ResultSet对象的敏感性。ResultSet有3种不同的类型,分别说明如下。

(1)TYPE_FORWARD_ONLY

​ 这种类型的ResultSet不可滚动,游标只能向前移动,从第一行到最后一行,不允许向后移动,即只能使用ResultSet接口的next()方 法,而不能使用previous()方法,否则会产生错误。

(2)TYPE_SCROLL_INSENSITIVE

​ 这种类型的ResultSet是可滚动的,它的游标可以相对于当前位置向前或向后移动,也可以移动到绝对位置。当ResultSet没有关闭 时,ResultSet的修改对数据库不敏感,也就是说对ResultSet对象的修改不会影响对应的数据库中的记录。

(3)TYPE_SCROLL_SENSITIVE

​ 这种类型的ResultSet是可滚动的,它的游标可以相对于当前位置向前或向后移动,也可以移动到绝对位置。当ResultSet没有关闭时,对ResultSet对象的修改会直接影响数据库中的记录。

当ResultSet没有关闭时,对ResultSet对象的修改会直接影响数据库中的记录。

默认情况下,ResultSet的类型为TYPE_FORWARD_ONLY。DatabaseMetaData接口中提供了一个supportsResultSetType()方法,用于判断数据库驱动是否支持某种类型的ResultSet对象,如果支持,则返回true,否则返回false。如果JDBC驱动不支持某一类型的ResultSet对象,在调用Connection对象的createStatement()、prepareStatement()或prepareCall()方法指定创建该类型的ResultSet对象时,会在Connection对象中产生一个SQLWarning对象,当Statement对象执行时,产生的ResultSet对象可以通过ResultSet对象的getType()方法确定它的类型。

ResultSet并行性

ResultSet对象的并行性决定了它支持更新的级别,目前JDBC中支持两个级别,分别如下:

CONCUR_READ_ONLY:为ResultSet对象设置这种属性后,只能从ResulSet对象中读取数据,但是不能更新ResultSet对象中的数据。

CONCUR_UPDATABLE:该属性表明,既可以从ResulSet对象中读取数据,又能更新ResultSet中的数据。

ResultSet对象默认并行性为CONCUR_READ_ONLY。DatabaseMetaData接口中提供了一个supportsResultSetConcurrency()方法,用于判断JDBC驱动是否支持某一级别的并行性,如果支持就返回true,否则返回false。

如果JDBC不支持某一级别的并行性,则调用createStatement()、prepareStatement()或prepareCall()方法指定该级别时会在Connection对象中产生一个SQLWarning对象。在应用程序中,可以调用ResultSet对象的getConcurrency()方法获取ResultSet的并行性级别。

ResultSet可保持性

调用Connection对象的commit()方法能够关闭当前事务中创建的ResultSet对象。然而,在某些情况下,这可能不是我们期望的行为。ResultSet对象的holdability属性使得应用程序能够在Connection对象的commit()方法调用后控制ResultSet对象是否关闭。

下面两个常量用于在调用Connection对象的createStatement()、prepareStatement()或prepareCall()方法时指定ResultSet对象的可保持性。

HOLD_CURSORS_OVER_COMMIT:当调用Connection对象的commit()方法时,不关闭当前事务创建的ResultSet对象。

CLOSE_CURSORS_AT_COMMIT:当前事务创建的ResultSet对象在事务提交后会被关闭,对一些应用程序来说,这样能够提升系统性能。

ResultSet对象的默认可保持性取决于具体的驱动实现,DatabaseMetaData接口中提供了getResultSetHoldability()方法用于获取JDBC驱动的默认可保持性。如果JDBC驱动不支持某一级别的可保持性,则调用createStatement()、prepareStatement()或prepareCall()方法指定该级别时,会在Connection对象中产生一个SQLWarning对象,应用程序可以调用ResultSet对象的getHoldability()方法获取ResultSet的可保持性。

ResultSet属性设置

ResultSet的类型、并行性和可保持性等属性可以在调用Connection对象的createStatement()、prepareStatement()或prepareCall()方法创建Statement对象时设置

ResultSet游标移动

ResultSet对象中维护了一个游标,游标指向当前数据行。当ResultSet对象第一次创建时,游标指向数据的第一行。ResultSet接口中提供了一系列的方法,用于操作ResultSet对象中的游标,这些方法的作用如下。

next():游标向前移动一行,如果游标定位到下一行,则返回true;如果游标位于最后一行之后,则返回false。

previous():游标向后移动一行,如果游标定位到上一行,则返回true;如果游标位于第一行之前,则返回false。

first():游标移动到第一行,如果游标定位到第一行,则返回true;如果ResultSet对象中一行数据都没有,则返回false。

last():移动游标到最后一行,如果游标定位到最后一行,则返回true;如果ResultSet不包含任何数据行,则返回false。

beforeFirst():移动游标到ResultSet对象的第一行之前,如果ResultSet对象不包含任何数据行,则该方法不生效。

afterLast():游标位置移动到ResultSet对象最后一行之后,如果ResultSet对象中不包含任何行,则该方法不生效。

relative(int rows):相对于当前位置移动游标,如果参数rows为0,则游标不会移动。如果rows为正数,则游标向前移动指定的行数,如果rows大于当前位置到最后一行的偏移量,则游标移动到最后一行之后。如果rows为负数,则游标向后移动,如果rows大于当前位置到第一行的偏移量,则游标移动到第一行之前的位置。当游标正确定位到某一行时,该方法返回true,否则返回false。如果参数rows值为1,则该方法的效果和next()方法相同;如果rows参数为-1,则该方法的效果和previous()方法相同。

absolute(int row):游标定位到ResultSet对象中的第row行。如果row为正数,则游标移动到ResultSet对象的第row行。需要注意的是,这里行的序数从1开始。如果参数row大于ResultSet对象中的最大行数,则游标移动到最后一行之后。如果参数row为负数,游标从行尾开始移动。例如,row值为-1时,游标移动到最后一行;为-2时,游标移动到倒数第二行;如果row的绝对值大于最大行,则游标移动到第一行之前。

注意:当ResultSet对象的类型为TYPE_FORWARD_ONLY时,游标只能向前移动,调用其他方法操作游标向后移动时将会抛出SQLException异常

修改ResultSet对象

并行性为CONCUR_UPDATABLE的ResultSet对象可以使用ResultSet接口中提供的方法对其进行更新,包括更新行、删除行,在JDBC驱动支持的情况下,还可以插入新的行。

@Test
  public void resultSetTest() throws SQLException {
    Connection connection = DriverManager.getConnection("jdbc:mysql://xxxx/demo",
      "xxxx",
      "xxxx");

    connection.setAutoCommit(false);

    Statement statement = connection.createStatement(
      ResultSet.TYPE_FORWARD_ONLY,
      ResultSet.CONCUR_UPDATABLE);

    ResultSet resultSet = statement.executeQuery("select * from demo1");

    resultSet.next();
    resultSet.updateString("name", "lyj1");
    resultSet.updateRow();

    resultSet.moveToInsertRow();
    resultSet.updateString("name","daitao2");
    resultSet.insertRow();
    
    resultSet.absolute(2);
    resultSet.deleteRow();

    connection.commit();

    resultSet.close();
    statement.close();
    connection.close();
  }
  • 删除数据

    将ResultSet对象的游标定位到某一行后,调用deleteRow()方法会删除数据库中对应的行。这种删除对于一个打开的ResultSet对象是可见的,它会反映到ResultSet对象的变化—ResultSet对象会移除对应的行,或者把对应的行设置为空或无效行。若如此,则调用DatabaseMetaData对象的ownDeletesAreVisible(int type)方法将返回true。如果调用deleteRow()方法删除行后ResultSet对象中仍然包含该行,那么调用DatabaseMetaData对象的ownDeletesAreVisible(int type)方法将返回false,意味着数据删除对当前ResultSet对象不可见。

    将ResultSet对象的游标定位到某一行后,调用deleteRow()方法会删除数据库中对应的行。这种删除对于一个打开的ResultSet对象是可见的,它会反映到ResultSet对象的变化—ResultSet对象会移除对应的行,或者把对应的行设置为空或无效行。若如此,则调用DatabaseMetaData对象的ownDeletesAreVisible(int type)方法将返回true。如果调用deleteRow()方法删除行后ResultSet对象中仍然包含该行,那么调用DatabaseMetaData对象的ownDeletesAreVisible(int type)方法将返回false,意味着数据删除对当前ResultSet对象不可见。

  • 插入数据

    ResultSet对象中插入行需要以下几步:

    (1)移动游标到待插入的位置。

    (2)调用ResultSet接口提供的updateXXX()方法为每一个字段设置值。

    (3)插入行到当前ResultSet对象中。

    需要注意的是,插入行中的每一个字段不允许为null,必须使用合适的updateXXX()方法指定一个确定的值。如果updateXXX()方法指定的值与数据库字段类型不匹配,那么调用insertRow()方法会抛出SQLException异常。如果新插入的行对ResultSet对象可见,那么调用DatabaseMetaData对象的ownInsertsAreVisible(int type)方法时返回true,否则返回false。如果新插入的行对其他事务中的ResultSet对象可见,则调用DatabaseMetaData对象的othersInsertsAreVisible(int type)方法返回true。如果ResultSet对象能够识别新插入的行,那么调用DatabaseMetaData对象的insertsAreDetected(int type)方法将会返回true,意味着插入行对ResultSet对象可见。

  • 更新数据

    如上面的代码所示,执行查询SQL生成ResultSet对象后,调用next()方法将游标定位到第一行,然后调用updateString()方法更新第一行的author字段,接着调用ResultSet的updateRow()方法将ResultSet对象的修改应用到数据库。

    DatabaseMetaData接口中的ownUpdatesAreVisible(int type)方法用于判断指定类型的ResultSet对象的更新是否对当前事务可见,如果可见,就返回true,否则返回false。

    DatabaseMetaData接口的othersUpdatesAreVisible(int type)方法用于判断指定类型的ResultSet对象的更新是否对其他事务可见,如果可见,就返回true,否则返回false。

    ResultSet对象可以调用rowUpdated()方法来判断是否调用了updateRow()方法确认更新。对于任何给定的ResultSet,应用程序不应该在调用updateXXX()方法之后以及在调用后续的updateRow()或cancelRowUpdates()方法之前修改通过updateXXX()方法设置的参数值,否则可能会产生不可预期的效果。

注意:对于一个给定的ResultSet对象,调用updateXXX()方法为每一个字段设置值后,在insertRow()方法调用前,应用程序不可以修改参数值,否则可能产生不可预料的结果。

关闭ResultSet对象

ResultSet对象在下面两种情况下会显式地关闭:

(1)调用ResultSet对象的close()方法。

(2)创建ResultSet对象的Statement或者Connection对象被显式地关闭。

在下面两种情况下ResultSet对象会被隐式地关闭:

(1)相关联的Statement对象重复执行时。

(2)可保持性为CLOSE_CURSORS_AT_COMMIT的ResultSet对象在当前事务提交后会被关闭。

注意:

一些JDBC驱动实现,当ResultSet类型为TYPE_FORWARD_ONLY并且next()方法返回false时,也会隐式地关闭ResultSet对象。一旦ResultSet对象被关闭,调用除isClosed()和close()之外的方法就会抛出SQLException异常,但是通过ResultSet创建的ResultSetMetaData实例仍然可以访问。

ResultSet对象关闭后,不会关闭由ResultSet对象创建的Blob、Clob、NClob或SQLXML对象,除非调用这些对象的free()方法。

注意:摘要于《mybatis3源码深度解析》

标签:调用,对象,ResultSet,游标,详解,移动,方法
From: https://www.cnblogs.com/daitao-blog/p/17282181.html

相关文章

  • Vue3【Axios网络请求(GET、POST 、并发请求、全局配置 )】(八)-全面详解(学习总结---从入
    ......
  • Vue3【Transition(效果、CSS 过渡、使用animation、TransitionGroup、 KeepAlive、Tele
    ......
  • 原码、反码、补码和移码详解
    计算入门原码:正数是其二进制本身;负数是符号位为1,数值部分取X绝对值的二进制。反码:正数的反码和原码相同;负数是符号位为1,其它位是原码取反。补码:正数的补码和原码,反码相同;负数是符号位为1,其它位是原码取反,未位加1。(或者说负数的补码是其绝对值反码未位加1)移码:将符号位取反......
  • Java 序列化详解
    XML和JSON是两种经常在网络使用的数据表示格式,这里我们介绍如何使用Java读写XML和JSON。 一、XML概述1、XML简介我们都知道对象是不能在网络中直接传输的,不过还有补救的办法。XML(ExtensibleMarkupLanguage)可扩展标记语言,本身就被设计用来存储数据,任何一个对象都可以用XML来描......
  • Python 数据结构与算法详解
    一、数据结构与算法1、算法提出1.算法概念算法是计算机处理信息的本质,因为计算机程序本质上是一个算法来告诉计算机按照确切的步骤来执行一个指定的任务。一般地,当算法在处理信息时,会从输入设备或数据的存储地址读取数据,把结果写入输出设备或某个存储地址供以后再调用。算法是独立......
  • 【UNCTF逆向】pytrade详解
    前段时间有点别的东西在忙,最近会加大力度。题目pytrade解法这道题的内容是一些opcode也就是python编译的字节码。网上搜的一些教程是叫手扒,就简单学习了一下。变量constfast(有形参和局部变量之分)global(全局)数据结构listdictionaryslice循环whileforinif函数函数范......
  • 【入门】Go语言指针详解
    目录一、指针介绍1.1什么是指针?1.2指针有什么用?二、指针的定义三、指针操作注意事项3.1空指针3.2操作没有合法指向的内存3.3new()函数使用一、指针介绍1.1什么是指针?指针是一种存储变量内存地址的变量。Go语言中的指针与C/C++中的指针类似,但是Go语言中的指针不能......
  • 【入门】Go语言结构体(struct)详解
    目录一、结构体介绍1.1什么是结构体?二、结构体定义与初始化2.1结构体定义2.2结构体初始化三、拓展3.1结构体与数组3.2结构体与切片3.3结构体与map3.4结构体作为函数参数一、结构体介绍1.1什么是结构体?结构体是一种自定义的数据类型,用于表示一组相关的数据字段。结构......
  • FTP状态码详解
    目录详细分解1xx–肯定的初步答复110120125150原因2xx–肯定的完成答复202211212213214215220221225226原因227230原因2502573xx–肯定的中间答复331原因3323504xx–瞬态否定的完成答复421425426原因4504514525xx–永久性否定的完成答复500501502503504530原因532550原......
  • Python异常 ValueError的问题详解
    导读这篇文章主要介绍了Python异常ValueError的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教Python异常ValueErrorValueError:invalidliteralforint()withbase10:'*'试图将一个与数字无关的类型转化为整数,会抛出该异常。......