| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> 疯狂Java讲义(十三)----第五部分 -> 正文阅读 |
|
[Java知识库]疯狂Java讲义(十三)----第五部分 |
?1.? Javar 的 RowSet????????RowSet接口继承了ResultSet接口,RowSet接口下包含JdbcRowSet.CachedRowSet、FilteredRowSet、JoinRowSet和 WebRowSet 常用子接口。除JdbcRowSet需要保持与数据库的连接之外,其余4个子接口都是离线的RowSet,无须保持与数据库的连接。 ?图13.22显示了RowSet规范的接口类图。 ????????在图13.22所示的各种接口中,CachedRowSet 及其子接口都代表了离线RowSet,它们都不需要底层数据库连接。 ? (1)?Java 7新增的RowSetFactory 与 RowSet????????Java 7新增了RowSetProvider类和 RowSetFactory接口,其中 RowSetProvider 负责创建RowSetFactory,而 RowSetFactory则提供了如下方法来创建RowSet实例。
????????通过使用RowSetFactory,就可以把应用程序与RowSet 实现类分离开,避免直接使用JdbcRow Setlmpl等非公开的API,也更有利于后期的升级、扩展。
下面程序通过RowSetFactory示范了使用JdbcRowSet的可滚动、可修改特性。 ????????上面程序中的粗体字代码使用了 RowSetFactory来创建JdbcRowSet对象,这就避免了与JdbcRowSetImpl实现类耦合。由于通过这种方式创建的JdbcRowSet还没有传入Connection参数,因此程序还需调用setUrl()、setUsername()、setPassword()等方法来设置数据库连接信息。 ? ? (2)?离线RowSet????????在使用ResultSet的时代,程序查询得到ResultSet之后必须立即读取或处理它对应的记录,否则一旦Connection关闭,再去通过ResultSet读取记录就会引发异常。在这种模式下,JDBC编程十分痛苦——假设应用程序架构被分为两层:数据访问层和视图显示层,当应用程序在数据访问层查询得到ResultSet之后,对 ResultSet的处理有如下两种常见方式。
????????第一种方式比较安全,但编程十分烦琐;第二种方式则需要Connection一直处于打开状态,这不仅不安全,而且对程序性能也有较大的影响。 ????????上面程序中的①号粗体字代码调用了RowSet 的 populate(ResultSet rs)方法来包装给定的ResultSet,接下来的粗体字代码关闭了ResultSet.Statement.Connection等数据库资源。如果程序直接返回ResultSet,那么这个ResultSet无法使用——因为底层的Connection已经关闭;但程序返回的是CachedRowSet,它是一个离线RowSet,因此程序依然可以读取、修改RowSet中的记录。 ? ? (3)?离线RowSet的查询分页????????由于CachedRowSet 会将数据记录直接装载到内存中,因此如果 SQL查询返回的记录过大,CachedRowSet将会占用大量的内存,在某些极端的情况下,它甚至会直接导致内存溢出。
下面程序示范了CachedRowSet的分页支持。 ????????上面两行粗体字代码就是使用CachedRowSet实现分页的关键代码。程序中①号代码显示要查询第2页的记录,每页显示3条记录。运行上面程序,可以看到程序只会显示从第4行到第6行的记录,这就实现了分页。 2.事务处理????????对于任何数据库应用而言,事务都是非常重要的,事务是保证底层数据完整的重要手段,没有事务支持的数据库应用,那将非常脆弱。 ? (1)?事务的概念和 MySQL事务支持????????事务是由一步或几步数据库操作序列组成的逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。程序和事务是两个不同的概念。一般而言,一段程序中可能包含多个事务。
数据库的事务由下列语句组成。
????????DDL和 DCL语句最多只能有一条,因为DDL和DCL语句都会导致事务立即提交。
????????当事务所包含的任意一个数据库操作执行失败后,应该回滚( rollback)事务,使该事务中所做的修改全部失效。事务回滚有两种方式:显式回滚和自动回滚。
????????MySQL默认关闭事务(即打开自动提交),在默认情况下,用户在MySQL控制台输入一条DML语句,这条DML语句将会立即保存到数据库里。为了开启MySQL 的事务支持,可以显式调用如下命令: ?????????一旦在 MySQL的命令行窗口中输入 set autocommit=0开启了事务,该命令行窗口里的所有DML语句都不会立即生效,上一个事务结束后第一条DML语句将开始一个新的事务,而后续执行的所有SQL语句都处于该事务中,除非显式使用commit 来提交事务,或者正常退出,或者运行DDL、DCL 语句导致事务隐式提交。当然,也可以使用rollback回滚来结束事务,使用rollback 结束事务将导致本次事务中 DML语句所做的修改全部失效。 ????????除此之外,如果不想关闭整个命令行窗口的自动提交,而只是想临时性地开始事务,则可以使用MySQL 提供的 start transaction或 begin两个命令,它们都表示临时性地开始一次事务,处于starttransaction或 begin后的 DML 语句不会立即生效,除非使用commit显式提交事务,或者执行 DDL、DCL语者来隐式提交事务。如下SOL代码将不会对数据库有任何影响。 ????????执行上面SQL语句中的第①条查询语句将会看到刚刚插入的3条记录,如果打开MySQL 的其他命令行窗口将看不到这3条记录——这正体现了事务的隔离性。接着程序rollback了事务中的全部修改,执行第②条查询语句时将看到数据库又恢复到事务开始前的状态。 ? (2)? JDBC的事务支持????????JDBC 连接也提供了事务支持,JDBC连接的事务支持由Connection提供,Connection默认打开自动提交,即关闭事务,在这种情况下,每条SQL语句一旦执行,便会立即提交到数据库,永久生效,无法对其进行回滚操作。 ????????程序中还可调用Connection提供的getAutoCommit()方法来返回该连接的自动提交模式。 ????????上面这些SOL语句虽然被执行了,但这些SQL语句所做的修改不会生效,因为事务还没有结束。如果所有的SQL语句都执行成功,程序可以调用Connection的commit()方法来提交事务,如下代码所示: ????????如果任意一条SQL语句执行失败,则应该用Connection的 rollback()方法来回滚事务,如下代码所示: ????????下面程序示范了当程序出现未处理的SQLException异常时,系统将自动回滚事务。 ????????上面程序中的粗体字代码只是开启事务、提交事务的代码,并没有回滚事务的代码。但当程序执行到第4条SQL语句(①处代码)时,这条语句将会引起外键约束异常,该异常没有得到处理,引起程序非正常结束,所以事务自动回滚。
????????通常来说,设置中间点时没有太大的必要指定名称,因为 Connection回滚到指定中间点时,并不是根据名字回滚的,而是根据中间点对象回滚的,Connection提供了rollback(Savepoint savepoint)方法回滚到指定中间点。 ? (3)?Java8增强的批量更新????????JDBC 还提供了一个批量更新的功能,使用批量更新时,多条SQL语句将被作为一批操作被同时收集,并同时提交。 ????????使用批量更新也需要先创建一个Statement对象,然后利用该对象的addBatch()方法将多条SQL语句同时收集起来,最后调用Java 8为Statement对象新增的executeLargeBatch()(或原有的executeBatch())方法同时执行这些SQL语句。只要批量操作中任何一条SQL语句影响的记录条数可能超过Integer.MAX_VALUE,就应该使用executeLargeBatch()方法,而不是executeBatch()方法。 ????????执行executeLargeBatch()方法将返回一个long[]数组,因为使用Statement执行DDL、DML 语句都将返回一个long值,而执行多条DDL、DML语句将会返回多个long值,多个long值就组成了这个long[]数组。如果在批量更新的addBatch()方法中添加了select查询语句,程序将直接出现错误。 ? 3.分析数据库信息????????大部分时候,只需要对指定数据表进行插入(C)、查询(R)、修改(U)、删除(D)等CRUD操作;但在某些时候,程序需要动态地获取数据库的相关信息,例如数据库里的数据表信息、列信息。除此之外,如果希望在程序中动态地利用底层数据库所提供的特殊功能,则都需要动态分析数据库相关信息。 ? (1)?使用DatabaseMetaData分析数据库信息????????JDBC提供了DatabaseMetaData来封装数据库连接对应数据库的信息,通过 Connection提供的getMetaData()方法就可以获取数据库对应的DatabaseMetaData对象。 ????????上面程序中的粗体字代码就是使用DatabaseMetaData分析数据库信息的示例代码。运行上面程序,将可以看到通过DatabaseMetaData分析数据库信息的结果。 ? (2)?使用系统表分析数据库信息????????除可以使用DatabaseMetaData来分析底层数据库信息之外,如果已经确定应用程序所使用的数据库系统,则可以通过数据库的系统表来分析数据库信息。前面已经提到,系统表又称为数据字典,数据字典的数据通常由数据库系统负责维护,用户通常只能查询数据字典,而不能修改数据字典的内容。 ????????MySQL 数据库使用information_schema数据库来保存系统表,在该数据库里包含了大量系统表,常用系统表的简单介绍如下。
????????从这些系统表中取得的数据库信息会更加准确,例如,若要查询当前MySQL数据库中包含多少数据库及其详细信息,则可以查询 schemata 系统表;如果需要查询指定数据库中的全部数据表,则可以查询tables系统表;如果需要查询指定数据表的全部数据列,就可以查询columns系统表。图13.23显示了通过系统表查询所有的数据库、select_test 数据库的全部数据表、student_table表的所有数据列的sQL语句及执行效果。 ? ? (3) 选择合适的分析方式????????本章后面的练习需要完成一个仿SQLyog应用程序,这个应用程序需要根据数据库、表、列等信息创建一棵树,这就需要利用DatabaseMetaData来分析数据库信息,或者利用MySQL系统表来分析数据库信息。 ? 4.使用连接池管理连接????????数据库连接的建立及关闭是极耗费系统资源的操作,在多层结构的应用环境中,这种资源的耗费对系统性能影响尤为明显。通过前面介绍的方式(通过DriverManager获取连接)获得的数据库连接,一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完后立即关闭连接。频繁地打开、关闭连接将造成系统性能低下。 ????????对于共享资源的情况,有一个通用的设计模式:资源池(Resource Pool),用于解决资源的频繁请求、释放所造成的性能下降。为了解决数据库连接的频繁请求、释放,JDBC 2.0规范引入了数据库连接池技术。数据库连接池是Connection对象的工厂。数据库连接池的常用参数如下。
????????JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由商用服务器(如WebLogic、WebSphere)等提供实现,也有一些开源组织提供实现(如DBCP和C3PO等)。 ????????本节不打算介绍任何商用服务器的数据源实现,主要介绍 DBCP和 C3PO两种开源的数据源实现。 ? (1)?DBCP数据源????????DBCP是 Apache 软件基金组织下的开源连接池实现,该连接池依赖该组织下的另一个开源系统:common-pool。如果需要使用该连接池实现,则应在系统中增加如下两个jar文件。
????????登录http:llcommons.apache.org/站点即可下载commons-pool.zip和commons-dbcp.zip两个压缩文件,解压缩这两个文件即可得到上面提到的两个JAR文件。为了在程序中使用这两个JAR文件,应该把它们添加到系统的类加载路径中(比如添加到CLASSPATH环境变量中)。 ????????数据源和数据库连接不同,数据源无须创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。也就是说,对于一个应用,上面代码只要执行一次即可。建议把上面程序中的 ds设置成static成员变量,并且在应用开始时立即初始化数据源对象,程序中所有需要获取数据库连接的地方直接访问该ds对象,并获取数据库连接即可。通过 DataSource获取数据库连接的代码示例如下: ????????但上面代码并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给连接池,让其他客户端可以使用该连接。 ? (2)?C3PO数据源????????相比之下,C3P0 数据源性能更胜一筹,Hibernate 就推荐使用该连接池。C3PO连接池不仅可以自动清理不再使用的Connection,还可以自动清理Statement和 ResultSet。C3PO连接池需要版本为1.3以上的JRE,推荐使用1.4以上的JRE。如果需要使用C3PO连接池,则应在系统中增加如下JAR文件。
????????登录http:lsourceforge.net/projects/c3pO/站点即可下载C3PO 数据源的最新版本,下载后得到一个c3p0-0.9.1.2.bin.zip文件(版本号可能有区别),解压缩该文件,即可得到上面提到的JAR文件。 ????????在程序中创建C3PO连接池的方法与前面介绍的创建DBCP连接池的方法基本类似,此处不再解释。一旦获取了C3PO连接池之后,程序同样可以通过如下代码来获取数据库连接。 ? 5.本章小结????????本章从标准的SQL语句讲起,简单介绍了关系数据库的基本理论及标准的SQL 语句的相关语法,包括DDL、DML、简单查询语句、多表连接查询和子查询语句。本章重点讲解了JDBC 数据库访问的详细步骤,包括加载数据库驱动,获取数据库连接,执行SQL语句,处理执行结果等。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 1:18:24- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |