疯狂Java讲义(十三)----第三部分

1.SQL语法

  (10) 数据库函数

        正如前面看到的连接字符串使用的concat 函数,每个数据库都会在标准的SQL基础上扩展一些函数,这些函数用于进行数据处理或复杂计算,它们通过对一组数据进行计算,得到最终需要的输出结果。函数一般都会有一个或者多个输入,这些输入被称为函数的参数,函数内部会对这些参数进行判断和计算,最终只有一个值作为返回值。函数可以出现在SQL语句的各个位置,比较常用的位置是select之后和 where子句中。
        根据函数对多行数据的处理方式,函数被分为单行函数和多行函数,单行函数对每行输入值单独计算,每行得到一个计算结果返回给用户;多行函数对多行输入值整体计算,最后只会得到一个结果。单行函数和多行函数的示意图如图13.13所示。


        SOL中的函数和 Java语言中的方法有点相似,但SQL中的函数是独立的程序单元,也就是说,调用函数时无须使用任何类、对象作为调用者,而是直接执行函数。执行函数的语法如下:

        多行函数也称为聚集函数、分组函数,主要用于完成一些统计功能,在大部分数据库中基本相同。但不同数据库中的单行函数差别非常大,MySQL中的单行函数具有如下特征。

  • 单行函数的参数可以是变量、常量或数据列。单行函数可以接收多个参数,但只返回一个值。
  • 单行函数会对每行单独起作用,每行(可能包含多个参数)返回一个结果。
  • 使用单行函数可以改变参数的数据类型。单行函数支持嵌套使用,即内层函数的返回值是外层函数的参数。

        MySQL的单行函数分类如图13.14所示。
        MySQL数据库的数据类型大致分为数值型、字符型和日期时间型,所以MySQL分别提供了对应的函数。转换函数主要负责完成类型转换,其他函数又大致分为如下几类。

  • 位函数
  • 流程控制函数
  • 加密解密函数
  • 信息函数

        每个数据库都包含了大量的单行函数,这些函数的用法也存在一些差异,但有一点是相同的—―每个数据库都会为一些常用的计算功能提供相应的函数,这些函数的函数名可能不同,用法可能有差异,但所有数据库提供的函数库所能完成的功能大致相似,读者可以参考各数据库系统的参考文档来学习这些函数的用法。下面通过一些例子来介绍MySQL单行函数的用法。

        MySQL提供了如下几个处理null的函数。

  • ifnull(expr1,expr2):如果expr1为null,则返回expr2,否则返回expr1。
  • nullif(expr1,expr2):如果erpr1和 expr2相等,则返回null,否则返回exprl。
  • if(exprl,expr2,expr3):有点类似于?:三目运算符,如果expr1为 true,不等于0,且不等于null,则返回expr2,否则返回expr3。
  • isnull(exprl):判断expr1是否为null,如果为null则返回true,否则返回false。

        MySQL还提供了一个case函数,该函数是一个流程控制函数。case函数有两个用法,case 函数第一个用法的语法格式如下:

        case函数用value和后面的compare_value1、compare_value2、…依次进行比较,如果value和指定的compare_valuel相等,则返回对应的 resultl,否则返回else后的result。例如如下SQL语句:

        在第二个用法中,condition1、condition2都是一个返回boolean值的条件表达式,因此这种用法更加灵活。例如如下SQL语句:

        虽然此处介绍了一些 MySQL常用函数的简单用法,但通常不推荐在Java程序中使用特定数据库的函数,因为这将导致程序代码与特定数据库耦合;如果需要把该程序移植到其他数据库系统上时,可能需要打开源程序,重新修改SQL语句。

  (11) 分组和组函数

        组函数也就是前面提到的多行函数,组函数将一组记录作为整体计算,每组记录返回一个结果,而不是每条记录返回一个结果。常用的组函数有如下5个。

  • avg([distinct(all]expr):计算多行expr 的平均值,其中,expr可以是变量、常量或数据列,但其数据类型必须是数值型。还可以在变量、列前使用distinct或all 关键字,如果使用distinct,则表明不计算重复值;all用和不用的效果完全一样,表明需要计算重复值。
  • count({*|[distinct/all]expr}):计算多行expr的总条数,其中,expr可以是变量、常量或数据列,其数据类型可以是任意类型;用星号(*)表示统计该表内的记录行数; distinct 表示不计算重复值。
  • max(expr):计算多行 expr 的最大值,其中 expr可以是变量、常量或数据列,其数据类型可以是任意类型。
  • min(expr):计算多行expr的最小值,其中 expr可以是变量、常量或数据列,其数据类型可以是任意类型。
  • sum([distinct/all]expr):计算多行expr的总和,其中,expr可以是变量、常量或数据列,但其数据类型必须是数值型;distinct表示不计算重复值。
     

        对于可能出现null的列,可以使用ifnull函数来处理该列。

        值得指出的是,distinct 和*不同时使用,如下SQL语句有错误。

        在默认情况下,组函数会把所有记录当成一组,为了对记录进行显式分组,可以在 select 语句后使用group by子句,group by子句后通常跟一个或多个列名,表明查询结果根据一列或多列进行分组——当一列或多列组合的值完全相同时,系统会把这些记录当成一组。如下SQL语句所示:

        如果对多列进行分组,则要求多列的值完全相同才会被当成一组。如下SQL语句所示:

        对于很多数据库而言,分组计算时有严格的规则——如果查询列表中使用了组函数,或者select语句中使用了group by分组子句,则要求出现在select列表中的字段,要么使用组函数包起来,要么必须出现在group by子句中。这条规则很容易理解,因为一旦使用了组函数或使用了group by子句,都将导致多条记录只有一条输出,系统无法确定输出多条记录中的哪一条记录。
        对于MySQL 来说,并没有上面的规则要求,如果某个数据列既没有出现在group by 之后,也没有使用组函数包起来,则 MySQL会输出该列的第一条记录的值。图13.15显示了MySQL的处理结果。


        如果需要对分组进行过滤,则应该使用having子句,having子句后面也是一个条件表达式,只有满足该条件表达式的分组才会被选出来。having子句和 where子句非常容易混淆,它们都有过滤功能,但它们有如下区别。

  • 不能在 where子句中过滤组,where子句仅用于过滤行。过滤组必须使用having子句。
  • 不能在 where子句中使用组函数,having子句才可使用组函数。

        如下SQL语句所示:

  (12)  多表连接查询

        很多时候,需要选择的数据并不是来自一个表,而是来自多个数据表,这就需要使用多表连接查询。例如,对于上面的 student_table和 teacher_table两个数据表,如果希望查询出所有学生以及他的老师名字,这就需要从两个表中取数据。
        多表连接查询有两种规范,较早的SQL 92规范支持如下几种多表连接查询。

  • 等值连接。
  • 非等值连接。
  • 外连接。
  • 广义笛卡儿积。

        SQL99规范提供了可读性更好的多表连接语法,并提供了更多类型的连接查询。SQL99支持如下几种多表连接查询。

  • 交叉连接。
  • 自然连接。
  • 使用using子句的连接。
  • 使用on子句的连接。
  • 全外连接或者左、右外连接。

1. SQL 92的连接查询
        SQL92的多表连接语法比较简洁,这种语法把多个数据表都放在from之后,多个表之间以逗号隔开;连接条件放在 where之后,与查询条件之间用and逻辑运算符连接。如果连接条件要求两列值相等,则称为等值连接,否则称为非等值连接;如果没有任何连接条件,则称为广义笛卡儿积。SQL 92中多表连接查询的语法格式如下:

        多表连接查询中可能出现两个或多个数据列具有相同的列名,则需要在这些同名列之间使用表名前缀或表别名前缀作为限制,避免系统混淆。
        实际上,所有的列都可以增加表名前缀或表别名前缀。只是进行单表查询时,绝不可能出现同名列,所以系统不可能混淆,因此通常省略表名前缀。

        如下SQL语句查询出所有学生的资料以及对应的老师姓名。

        执行上面查询语句,将看到如图13.16所示的结果。上面的查询结果正好满足要求,可以看到每个学生以及他对应的老师的名字。实际上,多表查询的过程可理解成一个嵌套循环,这个嵌套循环的伪码如下:

        理解了上面的伪码之后,接下来即可很轻易地理解多表连接查询的运行机制。如果求广义笛卡儿积,则where子句后没有任何连接条件,相当于没有上面的if语句,广义笛卡儿积的结果会有n×m条记录。只要把 where后的连接条件去掉,就可以得到广义笛卡儿积,如下SQL语句所示:

        上面SOL语句的执行结果相当于if条件换成了s.java _teacher > t.teacher_id。
        如果还需要对记录进行过滤,则将过滤条件和连接条件使用and连接起来,如下SQL语句所示:

        虽然 MySQL不支持SQL92中的左外连接、右外连接,但本书还是有必要了解一下SQL92中的左外连接和右外连接。SQL 92中的外连接就是在连接条件的列名后增加括号包起来的外连接符(+或*,不同的数据库有一定的区别),当外连接符出现在左边时称为左外连接,出现在右边时则称为右外连接。如下SQL语句所示:

        外连接就是在外连接符所在的表中增加一个“万能行”,这行记录的所有数据都是null,而且该行可以与另一个表中所有不满足条件的记录进行匹配,通过这种方式就可以把另一个表中的所有记录选出来,不管这些记录是否满足连接条件。
        除此之外,还有一种自连接,正如前面介绍外键约束时提到的自关联,如果同一个表中的不同记录之间存在主、外键约束关联,例如把员工、经理保存在同一个表里,则需要使用自连接查询。

        如果需要查询该数据表中的所有员工名,以及每个员工对应的经理名,则必须使用自连接查询。所谓自连接就是把一个表当成两个表来用,这就需要为一个表起两个别名,而且查询中用的所有数据列都要加表别名前缀,因为两个表的数据列完全一样。下面的自连接查询可以查询出所有的员工名,以及对应的经理名。

 2.SQL 99的连接查询
        SQL 99的连接查询与SQL 92的连接查询原理基本相似,不同的是SQL 99连接查询的可读性更强——查询用的多个数据表显式使用xxx join连接,而不是直接依次排列在from之后,from后只需要放一个数据表;连接条件不再放在where之后,而是提供了专门的连接条件子句。

  • 交叉连接( cross join ):交叉连接效果就是SQL-92中的广义笛卡儿积,所以交叉连接无须任何连接条件,如下SQL语句所示:

  • 自然连接( natural join ):自然连接表面上看起来也无须指定连接条件,但自然连接是有连接条件的,自然连接会以两个表中的同名列作为连接条件;如果两个表中没有同名列,则自然连接与交叉连接效果完全一样——因为没有连接条件。如下SQL语句所示:

  •  using子句连接: using子句可以指定一列或多列,用于显式指定两个表中的同名列作为连接条件。假设两个表中有超过一列的同名列,如果使用natural join,则会把所有的同名列当成连接条件;使用using子句,就可显式指定使用哪些同名列作为连接条件。如下SQL语句所示:

        运行上面语句将出现一个错误,因为student_table表中并不存在名为teacher_id的列。也就是说,如果使用using子句来指定连接条件,则两个表中必须有同名列,否则就会出现错误。

  • on子句连接:这是最常用的连接方式,SQL99语法的连接条件放在on子句中指定,而且每个on子句只指定一个连接条件。这意味着:如果需要进行N表连接,则需要有N-1个join...on对。如下SQL语句所示:

        使用on子句的连接完全可以代替SQL 92中的等值连接、非等值连接,因为on子句的连接条件除等值条件之外,也可以是非等值条件。如下SQL语句就是SQL 99中的非等值连接。

  • 左、右、全外连接:这三种外连接分别使用left [outer] join、right [outer] join和 full [outer] join,这三种外连接的连接条件一样通过on子句来指定,既可以是等值连接条件,也可以是非等值连接条件。

下面使用右外连接,连接条件是非等值连接。

下面使用左外连接,连接条件是非等值连接。

        运行上面两条外连接语句并查看它们的运行结果,不难发现SQL 99外连接与SQL 92外连接恰好相反,SQL99左外连接将会把左边表中所有不满足连接条件的记录全部列出;SQL 99右外连接将会把右边表中所有不满足连接条件的记录全部列出。
        下面的SQL语句使用全外连接,连接条件是等值连接。

 SQL 99的全外连接将会把两个表中所有不满足连接条件的记录全部列出。

  (13) 子查询

        子查询就是指在查询语句中嵌套另一个查询,子查询可以支持多层嵌套。对于一个普通的查询语句而言,子查询可以出现在两个位置。

  • 出现在 from语句后当成数据表,这种用法也被称为行内视图,因为该子查询的实质就是一个临时视图。
  • 出现在where条件后作为过滤条件的值。

使用子查询时要注意如下几点。

  • 子查询要用括号括起来。
  • 把子查询当成数据表时(出现在 from之后),可以为该子查询起别名,尤其是作为前缀来限定数据列时,必须给子查询起别名。
  • 把子查询当成过滤条件时,将子查询放在比较运算符的右边,这样可以增强查询的可读性。
  • 把子查询当成过滤条件时,单行子查询使用单行运算符,多行子查询使用多行运算符。

        对于把子查询当成数据表是完全把子查询当做数据表来用,只是把之前的表名变成子查询(也可为子查询起别名),其他部分与普通查询没有任何区别。下面的SQL语句示范了把子查询当成数据表的用法。

        把子查询当成数据表的用法更准确地说是当成视图,可以把上面的SQL 语句理解成在执行查询时创建了一个临时视图,该视图名为t,所以这种临时创建的视图也被称为行内视图。理解了这种子查询的实质后,不难知道这种子查询可以完全代替查询语句中的数据表,包括在多表连接查询中使用这种子查询。
        还有一种情形:把子查询当成where条件中的值,如果子查询返回单行、单列值,则被当成一个标量值使用,也就可以使用单行记录比较运算符。例如如下SQL语句:

        上面查询语句中的子查询(粗体字部分)将返回一个单行、单列值(该值就是1),如果把上面查询语句的括号部分换成1,那么这条语句就再简单不过了——实际上,这就是这种子查询的实质,单行、单列子查询的返回值被当成标量值处理。
        如果子查询返回多个值,则需要使用in、any和 all等关键字,in可以单独使用,与前面介绍比较运算符时所讲的in完全一样,此时可以把子查询返回的多个值当成一个值列表。如下SQL 语句所示:

        上面查询语句中的子查询(粗体字部分)将返回多个值,这多个值将被当成一个值列表,只要student_id与该值列表中的任意一个值相等,就可以选出这条记录。
        any和 all可以与>、>=、<、=、<>、=等运算符结合使用,与any结合使用分别表示大于、大于等于、小于、小于等于、不等于、等于其中任意一个值;与all结合使用分别表示大于、大于等于、小于、小于等于、不等于、等于全部值。从上面介绍中可以看出,=any 的作用与in的作用相同。如下 SQL语句使用=any来代替上面的in。

        <ANY只要小于值列表中的最大值即可,>ANY只要大于值列表中的最小值即可。<All 要求小于值列表中的最小值,>All要求大于值列表中的最大值。
        下面的SQL语句选出 student_table表中 student_id 大于teacher_table表中所有teacher_id的记录。

        还有一种子查询可以返回多行、多列,此时where子句中应该有对应的数据列,并使用圆括号将多个数据列组合起来。如下SQL语句所示:

  (14) 集合运算

        select语句查询的结果是一个包含多条数据的结果集,类似于数学里的集合,可以进行交( intersect)、并(union)和差(minus)运算,select查询得到的结果集也可能需要进行这三种运算。
        为了对两个结果集进行集合运算,这两个结果集必须满足如下条件。

  • 两个结果集所包含的数据列的数量必须相等。
  • 两个结果集所包含的数据列的数据类型也必须一一对应。

1. union运算

union运算的语法格式如下:

 下面的SQL语句查询出所有教师的信息和主键小于4的学生信息。

2. minus运算
minus运算的语法格式如下:

        上面的语法格式十分简单,不过很遗憾,MySQL并不支持使用minus运算符,因此只能借助于子查询来“曲线”实现上面的minus运算。
        假如想从所有学生记录中“减去”与老师记录的ID相同、姓名相同的记录,则可进行如下的minus运算:

 不过,MySOL 并不支持这种运算。但可以通过如下子查询来实现上面运算。

3. intersect运算
intersect运算的语法格式如下:

        上面的语法格式十分简单,不过很遗憾,MySQL 并不支持使用intersect 运算符,因此只能借助于多表连接查询来“曲线”实现上面的intersect运算。
        假如想找出学生记录中与老师记录中的ID相同、姓名相同的记录,则可进行如下的intersect运算:

 不过,MySQL并不支持这种运算。但可以通过如下多表连接查询来实现上面运算。

        需要指出的是,如果进行 intersect运算的两个select子句中都包括了where条件,那么将intersect运算改写成多表连接查询后还需要将两个where条件进行and运算。假如有如下intersect运算的SQL语句:

2.JDBC的典型用法

掌握了标准的SQL命令语法之后,就可以开始使用JDBC 开发数据库应用了。
 

  (1) JDBC 4.2常用接口和类简介

        Java8支持JDBC4.2标准,JDBC 4.2在原有JDBC标准上增加了一些新特性。下面介绍这些JDBCAPI时会提到Java8新增的功能。

  1. DriverManager:用于管理JDBC驱动的服务类。程序中使用该类的主要功能是获取Connection对象,该类包含如下方法。
  • public static synchronized Connection getConnection(String url,String user, String pass) throwsSQLException:该方法获得url对应数据库的连接。
  1. Connection:代表数据库连接对象,每个Connection 代表一个物理连接会话。要想访问数据库,必须先获得数据库连接。该接口的常用方法如下。
  • .Statement createStatement() throws SQLExcetpion:该方法返回一个Statement对象。
  • PreparedStatement prepareStatement(String sql) throws SQLExcetpion:该方法返回预编译的Statement对象,即将SQL语句提交到数据库进行预编译。
  • CallableStatement prepareCall(String sql) throws SQLExcetpion:该方法返回CallableStatement对象,该对象用于调用存储过程。

        上面三个方法都返回用于执行SQL语句的Statement对象,PreparedStatement、CallableStatement是 Statement的子类,只有获得了Statement之后才可执行SQL语句。
        除此之外,Connection还有如下几个用于控制事务的方法。

  • Savepoint setSavepoint():创建一个保存点。
  • Savepoint setSavepoint(String name):以指定名字来创建一个保存点。
  • void setTransactionlsolation(int level):设置事务的隔离级别。
  • void rollback():回滚事务。
  • void rollback(Savepoint savepoint):将事务回滚到指定的保存点。
  • void setAutoCommit(boolean autoCommit):关闭自动提交,打开事务。
  • void commit():提交事务。

        Java 7为Connection新增了setSchema(String schema)、getSchema()两个方法,这两个方法用于控制该Connection访问的数据库Schema.Java 7还为Connection新增了setNetworkTimeout(Executor executor,int milliseconds)、getNetworkTimeout()两个方法来控制数据库连接的超时行为。

  1. Statement:用于执行SQL 语句的工具接口。该对象既可用于执行DDL、DCL语句,也可用于执行DML语句,还可用于执行SQL查询。当执行SQL查询时,返回查询到的结果集。它的常用方法如下。
  • ResultSet executeQuery(String sql)throws SQLException:该方法用于执行查询语句,并返回查询结果对应的ResultSet对象。该方法只能用于执行查询语句。
  • int executeUpdate(String sql)throws SQLExcetion:该方法用于执行DML语句,并返回受影响的行数;该方法也可用于执行DDL语句,执行 DDL语句将返回0。
  • boolean execute(String sql)throws SQLException:该方法可执行任何SQL语句。如果执行后第一个结果为ResultSet对象,则返回true;如果执行后第一个结果为受影响的行数或没有任何结果,则返回false。

        Java7为Statement新增了closeOnCompletion()方法,如果Statement 执行了该方法,则当所有依赖于该Statement的 ResultSet关闭时,该Statement 会自动关闭。Java 7还为Statement 提供了一个isCloseOnCompletion()方法,该方法用于判断该Statement 是否打开了“closeOnCompletion ”。
        Java 8为Statement 新增了多个重载的executeLargeUpdate()方法,这些方法相当于增强版的executeUpdate()方法,返回值类型为long——也就是说,当 DML语句影响的记录条数超过Integer.MAX_VALUE时,就应该使用executeLargeUpdate()方法。

  1.  PreparedStatement: 预编译的Statement对象。PreparedStatement 是Statement的子接口,它允许数据库预编译SQL语句(这些SQL语句通常带有参数),以后每次只改变SQL命令的参数,避免数据库每次都需要编译SQL语句,因此性能更好。相对于Statement 而言,使用PreparedStaterment执行SQL语句时,无须再传入SQL语句,只要为预编译的SQL语句传入参数值即可。所以它比Statement多了如下方法。
  • void setXxx(int parameterIndex,Xxx value): 该方法根据传入参数值的类型不同,需要使用不同的方法。传入的值根据索引传给SQL语句中指定位置的参数。

  1. ResultSet:结果集对象。该对象包含访问查询结果的方法,ResultSet可以通过列索引或列名获得列数据。它包含了如下常用方法来移动记录指针。
  • void close():释放ResultSet对象。
  • boolean absolute(int row):将结果集的记录指针移动到第row行,如果 row是负数,则移动到倒数第row行。如果移动后的记录指针指向一条有效记录,则该方法返回true。
  • void beforeFirst():将ResultSet的记录指针定位到首行之前,这是 ResultSet结果集记录指针的初始状态——记录指针的起始位置位于第一行之前。
  • boolean first():将ResultSet的记录指针定位到首行。如果移动后的记录指针指向一条有效记录,则该方法返回 true。
  • boolean previous():将ResultSet的记录指针定位到上一行。如果移动后的记录指针指向一条有效记录,则该方法返回true。
  • boolean next():将ResultSet的记录指针定位到下一行,如果移动后的记录指针指向一条有效记录,则该方法返回true。
  • boolean last():将ResultSet的记录指针定位到最后一行,如果移动后的记录指针指向一条有效记录,则该方法返回true。
  • void afterLast():将ResultSet的记录指针定位到最后一行之后。

        当把记录指针移动到指定行之后,ResultSet可通过getXxx(int columnIndex)或 getXxx(StringcolumnLabel)方法来获取当前行、指定列的值,前者根据列索引获取值,后者根据列名获取值。Java 新增了<T> T getObject(int columnIndex, Class<T> type)和<T>T getObject(String columnLabel, Class<T>type)两个泛型方法,它们可以获取任意类型的值。

  (2) JDBC编程步骤

        大致了解了JDBC API的相关接口和类之后,下面就可以进行JDBC编程了,JDBC编程大致按如下步骤进行。
        ①加载数据库驱动。通常使用Class类的forName()静态方法来加载驱动。例如如下代码:

        上面代码中的driverClass就是数据库驱动类所对应的字符串。例如,加载 MySQL的驱动采用如下代码:

        从上面代码中可以看出,加载驱动时并不是真正使用数据库的驱动类,只是使用数据库驱动类名的字符串而已。

        ②通过DriverManager 获取数据库连接。DriverManager提供了如下方法:

        当使用DriverManager获取数据库连接时,通常需要传入三个参数:数据库URL、登录数据库的用户名和密码。这三个参数中用户名和密码通常由DBA(数据库管理员)分配,而且该用户还应该具有相应的权限,才可以执行相应的SQL语句。
        数据库URL通常遵循如下写法:

        上面URL 写法中的jdbc是固定的,而 subprotocol 指定连接到特定数据库的驱动,而后面的other和 stuff也是不固定的——也没有较强的规律,不同数据库的URL写法可能存在较大差异。例如,MySQL数据库的URL写法如下:

③通过Connection对象创建Statement对象。Connection创建Statement的方法有如下三个。

  • createStatement():创建基本的Statement对象。
  • prepareStatement(String sql):根据传入的SQL语句创建预编译的Statement对象。
  • prepareCall(String sql):根据传入的SQL语句创建CallableStatement对象。

④使用Statement 执行SQL语句。所有的Statement都有如下三个方法来执行SQL语句。

  • execute():可以执行任何SQL语句,但比较麻烦。
  • executeUpdate():主要用于执行DML和 DDL语句。执行DML语句返回受SQL语句影响的行数,执行DDL语句返回0。
  • executeQuery():只能执行查询语句,执行后返回代表查询结果的ResultSet对象。

⑤操作结果集。如果执行的SQL语句是查询语句,则执行结果将返回一个ResultSet对象,该对象里保存了SQL语句查询的结果。程序可以通过操作该ResultSet对象来取出查询结果。ResultSet对象主要提供了如下两类方法。

  • next()、previous()、first()、last()、beforeFirst()、afterLast()、absolute()等移动记录指针的方法。
  • getXxx()方法获取记录指针指向行、特定列的值。该方法既可使用列索引作为参数,也可使用列名作为参数。使用列索引作为参数性能更好,使用列名作为参数可读性更好。

        ResultSet实质是一个查询结果集,在逻辑结构上非常类似于一个表。图13.17显示了ResultSet的逻辑结构,以及操作ResultSet 结果集并获取值的方法示意图。

        ⑥回收数据库资源,包括关闭ResultSet、Statement和 Connection等资源。下面程序简单示范了JDBC 编程,并通过ResultSet获得结果集的过程。

        上面程序严格按JDBC访问数据库的步骤执行了一条多表连接查询语句,这条连接查询语句就是前面介绍SQL92连接时所讲的连接查询语句。

        与前面介绍的步骤略有区别的是,本程序采用了自动关闭资源的try语句来关闭各种数据库资源,Java 7改写了Connection、Statement、ResultSet等接口,它们都继承了AutoCloseable接口,因此它们都可以由try语句来关闭。
        运行上面程序,会看到如图13.18所示的结果。

猜你喜欢

转载自blog.csdn.net/indeedes/article/details/121217066
今日推荐