(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的类型为TYPE_FORWARD_ONLY。DatabaseMetaData接口中供应了一个supportsResultSetType()方法,用于判断数据库驱动是否支持某种类型的ResultSet工具,如果支持,则返回true,否则返回false。如果JDBC驱动不支持某一类型的ResultSet工具,在调用Connection工具的createStatement()、prepareStatement()或prepareCall()方法指定创建该类型的ResultSet工具时,会在Connection工具中产生一个SQLWarning工具,当Statement工具实行时,产生的ResultSet工具可以通过ResultSet工具的getType()方法确定它的类型。
2.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的并行性级别。
3.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的可保持性。
4.ResultSet属性设置ResultSet的类型、并行性和可保持性等属性可以在调用Connection工具的createStatement()、prepareStatement()或prepareCall()方法创建Statement工具时设置,例如:
Connection conn = ds.getConnection(user, passwd);Statement stmt = conn.createStatement(ResultSet.TYPE SCROLL INSENSITIVE,ResultSet.CONCUR READ ONLY,ResultSet.CLOSE CURSORS AT COMMIT);
上面的代码中,创建Statement工具时,指定ResultSet工具可以滚动,ResultSet中的数据不可以修正,而且在调用Connection工具的commit()方法提交事务时当前事务创建的ResultSet工具自动关闭。Statement、PreparedStatement和CallableStatement接口中为这些属性供应了Getter方法,用于获取ResultSet的类型、并行性及可保持性等属性。
5.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非常。
6.修正ResultSet工具并行性为CONCUR_UPDATABLE的ResultSet工具可以利用ResultSet接口中供应的方法对其进行更新,包括更新行、删除行,在JDBC驱动支持的情形下,还可以插入新的行。
接下来我们就来理解一下如何利用ResultSet接口中供应的方法修正ResultSet工具。
首先来看一下如何更新ResultSet记录中的某一行,更新ResultSet工具中的某一行是一个两阶段的过程。首先须要为某一行的每个字段设置新的值,然后更新修正到详细的行。第一阶段完成后,底层数据库数据不会更新,第二阶段会把ResultSet工具的修正同步到数据库。ResultSet接口针对所有JDBC类型,供应了两个更新方法,个中一个方法须要指定更新列的序数,另一个方法须要指定列的名称(大小写不敏感)。如果在并行性级别为ResultSet.CONCUR_READ_ONLY的ResultSet工具上调用更新方法,将会抛出SQLException非常。ResultSet工具的updateRow()方法用于将所有列的修正运用到当前行,并打消先前更新方法所做变动的记录。
public void testJdbc() { // 初始化数据 DbUtils.initData(); try { // 加载驱动 Class.forName("org.hsqldb.jdbcDriver"); // 获取Connection工具 Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:mybatis", "sa", ""); Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet resultSet = statement.executeQuery("select from user limit 2"); // 遍历ResultSet ResultSetMetaData metaData = resultSet.getMetaData(); int columCount = metaData.getColumnCount(); while (resultSet.next()) { for (int i = 1; i <= columCount; i++) { String columName = metaData.getColumnName(i); String columVal = resultSet.getString(columName); System.out.println(columName + ":" + columVal); } System.out.println("--------------------------------------"); } // hsqldb 不支持 // 换成mysql System.out.println(connection.getMetaData().supportsResultSetType(ResultSet.CONCUR_UPDATABLE)); resultSet.first(); resultSet.updateString("NICK_NAME", "xuxu"); resultSet.updateRow(); System.out.println(resultSet.isClosed()); // 遍历ResultSet ResultSet resultSet2 = statement.executeQuery("select from rr_banner_bannermodel limit 1"); ResultSetMetaData metaData2 = resultSet2.getMetaData(); while (resultSet2.next()) { for (int i = 1; i <= columCount; i++) { String columName = metaData2.getColumnName(i); String columVal = resultSet2.getString(columName); System.out.println(columName + ":" + columVal); } System.out.println("--------------------------------------"); } // 关闭连接 IOUtils.closeQuietly(statement); IOUtils.closeQuietly(connection); } catch (Exception e) { e.printStackTrace(); } }
上面用的是hsqldb 驱动,hsqldb 驱动不支持CONCUR_READ_ONLY ,可以更新到mysql的驱动,这里只作为一个实例看看。
如上面的代码所示,实行查询SQL天生ResultSet工具后,调用next()方法将游标定位到第一行,然后调用updateString()方法更新第一行的nick_name字段,接着调用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工具中的某一行。ResultSet工具中的行可以调用deleteRow()方法进行删除,例如:
rs.absolute(4)rs.deleteRow
将ResultSet工具的游标定位到某一行后,调用deleteRow()方法会删除数据库中对应的行。这种删除对付一个打开的ResultSet工具是可见的,它会反响到ResultSet工具的变革—ResultSet工具会移除对应的行,或者把对应的行设置为空或无效行。若如此,则调用DatabaseMetaData工具的ownDeletesAreVisible(int type)方法将返回true。如果调用deleteRow()方法删除行后ResultSet工具中仍旧包含该行,那么调用DatabaseMetaData工具的ownDeletesAreVisible(int type)方法将返回false,意味着数据删除对当前ResultSet工具不可见。
DatabaseMetaData工具的othersDeletesAreVisible(int type)方法用于判断数据行的删除对其他事务中的ResultSet工具是否可见,如果返回值为true,就表明当前ResultSet行的删除对其他事务中的ResultSet工具是可见的,否则返回false。当前行被删除后,如果ResultSet工具能够检测到行被删除,那么ResultSet工具的rowDeleted()方法会返回true,否则返回false。
末了,我们来理解一下如何向ResultSet工具中插入行。在JDBC驱动支持的情形下,可以调用ResultSet接供词给的方法向ResultSet工具中插入行。如果JDBC驱动不支持向ResultSet工具中插入行,就会抛出SQLFeatureNotSupportedException非常。
ResultSet工具中插入行须要以下几步:
(1)移动游标到待插入的位置。
(2)调用ResultSet接供词给的updateXXX()方法为每一个字段设置值。
(3)插入行到当前ResultSet工具中。
代码如下:
ResultSet rs = stmt.executeQuery("select author, title, isbn"from booklist");rs.moveToInsertRow();//为每列设置值rs.updateString(1,"Huxley, Aldous");rs.updateString(2,"Doors of Perception and Heaven and Hell");rs.updateLong(3,60900075);插入行rs.insertRow();//移动游标到插入前的行rs.moveToCurrentRow();
须要把稳的是,插入行中的每一个字段不许可为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工具可见。
对付一个给定的ResultSet工具,调用updateXXX()方法为每一个字段设置值后,在insertRow()方法调用前,运用程序不可以修正参数值,否则可能产生不可预见的结果。
7.关闭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()方法。