深入理解ResultSet

来自CloudWiki
跳转至: 导航搜索

ResultSet的概念

ResultSet,数据库结果集的数据表,通常通过执行查询数据库的语句生成。

如图7-4所示,ResultSet 对象具有指向其当前数据行的指针。最初,指针被置于第一行之前。next 方法将指针移动到下一行;因为该方法在 ResultSet 对象中没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。

Java20-9-1.png

图7-4 ResultSet中的指针

默认的 ResultSet 对象不可更新,仅有一个向前移动的指针。因此,只能迭代它一次,并且只能按从第一行到最后一行的顺序进行。可以生成可滚动和/或可更新的 ResultSet 对象。以下代码片段(其中 con 为有效的 Connection 对象)演示了如何生成可滚动且不受其他更新影响的、可更新的结果集。

Statement stmt = 
con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2"); 

ResultSet 接口提供用于从当前行检索列值的获取方法(getBoolean、getLong 等)。可以使用列的索引编号或列的名称检索值。一般情况下,使用列索引较为高效。列从 1 开始编号。为了获得最大的可移植性,应该按从左到右的顺序读取每行中的结果集列,而且每列只能读取一次。 对于获取方法,JDBC 驱动程序尝试将基础数据转换为在获取方法中指定的 Java 类型,并返回适当的 Java 值。JDBC 规范有一个表,显示允许的从 SQL 类型到供 ResultSet 获取方法使用的 Java 类型的映射关系。

用作获取方法的输入的列名称不区分大小写。用列名称调用获取方法时,如果多个列具有这一名称,则返回第一个匹配列的值。列名称选项在生成结果集的 SQL 查询中使用列名称时使用。对于没有在查询中显式命名的列,最好使用列编号。如果使用列名称,程序员无法保证名称实际所指的就是预期的列。

获取数据库元数据

在我们前面使用JDBC来处理数据库的接口主要有三个,即Connection,PreparedStatement和ResultSet这三个,而对于这三个接口,还可以获取不同类型的元数据,通过这些元数据类获得一些数据库的信息。

元数据(MetaData),即定义数据的数据。打个比方,就好像我们要想搜索一首歌(歌本身是数据),而我们可以通过歌名,作者,专辑等信息来搜索,那么这些歌名,作者,专辑等等就是这首歌的元数据。因此数据库的元数据就是一些注明数据库信息的数据。

  1. 由Connection对象的getMetaData()方法获取的是DatabaseMetaData对象。
  2. 由PreparedStatement对象的getParameterMetaData ()方法获取的是ParameterMetaData对象。
  3. 由ResultSet对象的getMetaData()方法获取的是ResultSetMetaData对象。

DatabaseMetaData是由Connection对象通过getMetaData方法获取而来,主要封装了是对数据库本身的一些整体综合信息,例如数据库的产品名称,数据库的版本号,数据库的URL,是否支持事务等等,能获取的信息比较多,具体可以参考DatabaseMetaData的API文档。以下有一些关于DatabaseMetaData的常用方法:

  • getDatabaseProductName:获取数据库的产品名称
  • getDatabaseProductName:获取数据库的版本号
  • getUserName:获取数据库的用户名
  • getURL:获取数据库连接的URL
  • getDriverName:获取数据库的驱动名称
  • driverVersion:获取数据库的驱动版本号
  • isReadOnly:查看数据库是否只允许读操作
  • supportsTransactions:查看数据库是否支持事务

如果简单地获取一些常用的数据库综合信息,可以进行如下编码:

        TestSQL t =new TestSQL();
        t.getConn();//建立mysql连接        
        
        DatabaseMetaData dbMetaData= t.conn.getMetaData(); 
        //获取数据库产品名称 
        String productName= dbMetaData.getDatabaseProductName(); 
        System.out.println("数据库产品名称:"+productName);
        //获取数据库版本号 
        String productVersion= dbMetaData.getDatabaseProductVersion(); //获取数据库用户名 
        System.out.println("数据库版本号:"+productVersion);
        String userName= dbMetaData.getUserName(); 
        System.out.println("用户名:"+userName);
        //获取数据库连接URL 
        String userUrl= dbMetaData.getURL();
        System.out.println("获取数据库连接URL:"+userUrl);
        //获取数据库驱动
        String driverName= dbMetaData.getDriverName();
        System.out.println("获取数据库驱动:"+driverName);
        //获取数据库驱动版本号
        String driverVersion= dbMetaData.getDriverVersion(); 
        System.out.println("获取数据库驱动版本号:"+driverVersion);
        //查看数据库是否是只读的
        boolean isReadOnly= dbMetaData.isReadOnly(); 
        System.out.println("数据库是否只读?"+isReadOnly);
        //查看数据库是否支持事务操作
        boolean supportsTransactions= dbMetaData.supportsTransactions();
        System.out.println("查看数据库是否支持事务操作:"+supportsTransactions);
	 

其中,conn是已获取的连接,上述代码运行结果如下:

数据库产品名称:MySQL
数据库版本号:5.5.65-MariaDB
用户名:root@10.0.0.1
获取数据库连接URL:jdbc:mysql://10.0.0.30:3306/cloud?characterEncoding=utf8
获取数据库驱动:MySQL Connector Java
获取数据库驱动版本号:mysql-connector-java-5.1.39 ( Revision: 3289a357af6d09ecc1a10fd3c26e95183e5790ad )
数据库是否只读?false
查看数据库是否支持事务操作:true

拓展与提高

在任务案例的代码中,对主界面代码和数据库访问代码进行了分离,提高了代码的可读性,但是,如果把一些逻辑代码和主界面混在一起,就极大地影响了代码的可读性、可维护性、可扩展性和执行效率。因此,业务逻辑代码需要独立出来,放在一个单独的类中,完成业务功能的同时担任主界面和数据库访问代码的桥梁,就好像饭店里的服务员和采购员之间,需要一个厨师一样,明确的人员分工不仅提高了运作效率,也降低了人员变动的风险。这种把数据访问代码、业务逻辑代码和页面代码相互分离的软件设计模式,就是当前比较流行的分层架构模式。

在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层、表示层。其中,数据访问层由数据库操作相关的代码组成,业务逻辑层由逻辑处理相关的代码组成,表示层由界面组成;它们之间通过方法的参数和返回值进行数据的传递。我们可以如图7-4所示,对代码进行优化。

Java7-11.png

知识点提炼

  1. ResultSet 对象的列的编号、类型和属性由 ResultSet.getMetaData 方法返回的 ResulSetMetaData 对象提供。
  2. 当生成 ResultSet 对象的 Statement 对象关闭、重新执行或用来从多个结果的序列检索下一个结果时,ResultSet 对象会自动关闭。
  3. 元数据(Metadata)是描述其它数据的数据(data about other data),或者说是用于提供某种资源的有关信息的结构数据(structured data)。元数据是描述信息资源或数据等对象的数据,其使用目的在于:识别资源;评价资源;追踪资源在使用过程中的变化;实现简单高效地管理大量网络化数据;实现信息资源的有效发现、查找、一体化组织和对使用资源的有效管理。

习题

一、选择题

1、哪个不是JDBC用到的接口和类? ( )

A. System B. Class C. Connection D. ResultSet

2、使用Connection 的哪个方法可以建立一个PreparedStatement接口?( )

A. createPrepareStatement() B. prepareStatement()

C. createPreparedStatement() D. preparedStatement()

3、在JDBC编程中执行完下列SQL语句SELECT name, rank, serialNo FROM employee,能得到rs的第一列数据的代码是哪两个? ( )

A. rs.getString(0) B. rs.getString("name")

C. rs.getString(1) D. rs.getString("ename")

4、下面的选项加载MySQL驱动正确的是哪一个? ( )

A. Class.forname("com.mysql.JdbcDriver")

B. Class.forname("com.mysql.jdbc.Driver")

C. Class.forname("com.mysql.driver.Driver")

D. Class.forname("com.mysql.jdbc.MySQLDriver")

5、如果为下列预编译SQL的第三个问号赋值,那么正确的选项是哪一个? ( )

UPDATE emp SET ename=?,job=?,salary=? WHERE empno=?;

A. pst.setInt("3",2000) B. pst.setInt(3,2000)

C. pst.setFloat("salary",2000) D.pst.setString("salary","2000")

二、简答题

1、结合实际案例说明Eclipse中利用JDBC技术连接到数据库的一般步骤。

2、列出Statement组件用于执行SQL语句的三个主要方法,并说明其作用。

三、编程题

数据表user,结构如下

文件:Java7-12.png

完成用户注册功能。

返回 Java程序设计