1、第第2章章 JDBC数据库编程数据库编程1.1 JDBC概述概述1.2 数据库基本操作数据库基本操作 1.3 数据库存取优化数据库存取优化 习题习题 2.1 JDBC概述概述2.1.1 JDBC数据库应用模型 JDBC由两层构成,一层是JDBC API,负责在Java应用程序与JDBC驱动程序管理器之间进行通信,负责发送程序中的SQL语句。其下一层是JDBC驱动程序API,与实际连接数据库的第三方驱动程序进行通信,返回查询信息或者执行规定的操作。如图所示。 1Java应用程序应用程序 Java程序包括应用程序、Applet以及Servlet,这些类型的程序都可以利用JDBC实现对数据库的访问,
2、JDBC在其中所起的作用包括:请求与数据库建立连接、向数据库发送SQL请求、处理查询、错误处理等操作。 2JDBC驱动程序管理器驱动程序管理器 JDBC驱动程序管理器动态地管理和维护数据库查询所需要的驱动程序对象,实现Java程序与特定驱动程序的连接。它完成的主要任务包括:为特定的数据库选取驱动程序、处理JDBC初始化调用、为每个驱动程序提供JDBC功能的入口、为JDBC调用传递参数等。3驱动程序驱动程序 驱动程序一般由数据库厂商或者第三方提供,由JDBC方法调用,向特定数据库发送SQL请求,并为程序获取结果。驱动程序完成下列的任务:建立与数据库的连接、向数据库发送请求、在用户程序请求时进行翻
3、译、错误处理。4数据库数据库 数据库指数据库管理系统和用户程序所需要的数据库。2.1.2 JDBC驱动程序JDBC驱动程序分为以下四种类型。(1)类型1,JDBC-ODBC Bridge Driver,这种驱动方式通过ODBC驱动器提供数据库连接。使用这种方式要求客户机装入ODBC驱动程序。(2)类型2,Native-API partly-Java Driver,这种驱动方式将数据库厂商所提供的特殊协议转换为Java代码及二进制代码,利用客户机上的本地代码库与数据库进行直接通信。和类型1一样,这种驱动方式也存在很多局限,由于使用本地库,因此,必须将这些库预先安装在客户机上。(3)类型3,JDB
4、C-Net All-Java Driver,这种类型的驱动程序是纯Java代码的驱动程序,它将JDBC指令转换成独立于DBMS的网络协议形式并与某种中间层连接,再通过中间层与特定的数据库通信。该类型驱动具有最大的灵活性,通常由非数据库厂商提供,是四种类型中最小的。(4)类型4,Native-protocol All-Java Driver,这种驱动程序也是一种纯Java的驱动程序,它通过本地协议直接与数据库引擎相连接。这种驱动程序也能应用于Internet。在全部四种驱动方式中,这种方式具有最好的性能。2.1.3 用JDBC访问数据库 用JDBC实现访问数据库要经历以下几个步骤:1建立数据源建
5、立数据源 这里的数据源是指ODBC数据源,这一点不是JDBC所必需的,而是当使用驱动程序类型1即JDBC-ODBC Bridge建立连接时所需要的步骤。2装入装入JDBC驱动程序驱动程序 DriverManager类管理各种数据库驱动程序,建立新的数据库连接。 JDBC驱动程序通过调用registerDriver方法进行注册。用户在正常情况下不会直接调用DriverManager.registerDriver,而是在加载驱动程序时由驱动程序自动调用。加载Driver类,自动在DriverManager中注册的方法有以下两种: (1)调用方法Class.forName()将显式地加载驱动程序类。
6、例如加载Sybase数据库驱动程序: Class.forName(“com.sybase.jdbc2.jdbc.SybDriver”); (2)通过将驱动程序添加到java.lang.System的属性jdbc.drivers中。初始化DriverManager类时,它自动搜索系统属性jdbc.drvers且加载其中包含的一个或多个驱动程序。例如下面的代码准备加载三个驱动程序类: jdbc.drivers = ei.bar.Driver:bee.sql.Driver:see.test.ourDriver;3建立连接建立连接 与数据库建立连接的方法包括: DriverManager.getCon
7、nection(String url) DriverManager.getConnection(String url,Properties pro) DriverManager.getConnection(String url,String user,String password) 其中,url指出使用哪个驱动程序以及连接数据库所需的其它信息。其格式为: jdbc:例如: String url = “jdbc:microsoft:sqlserver:/localhost:1433;User=JavaDB;Password=javadb;DatabaseName=northwind”;这里,s
8、ubprotocol为microsoft,而subname为sqlserver及其后的内容。至于用户名和口令也是存取数据所需的信息。有时候,可以采用另一种方式建立连接: String url = “jdbc:microsoft:sqlserver:/localhost:1433;DatabaseName=northwind”; Connection con = DriverManager.getConnection(url,”JavaDB”,”javadb”);4执行执行SQL语句语句与数据库建立连接之后,需要向访问的数据库发送SQL语句。在特定的程序环境和功能需求下,可能需要不同的SQL语句
9、,例如数据库的增删改查等操作,或者数据库或表的创建及维护操作等等。需要说明的是:Java程序中所用到的SQL语句是否能得到正确的执行,是否会产生异常或错误,需要关注的不仅是语句本身的语法正确性,而且关注所访问的数据库是否支持,例如有的数据库不支持存储过程操作,则发送调用存储过程的语句即抛出异常。有三个类用于向数据库发送SQL语句: (1)Statement 类,调用其createStatement()方法可以创建语句对象,然后利用该语句对象可以向数据库发送具体的SQL语句。例如: String query = “select * from table1”; /查询语句 Satement st
10、= con.createStatement(); /或用带参数的createStatement()方法 ResultSet rs = st.executeQuery(query); /发送SQL语句,获得结果 (2)PreparedStatement类,调用其方法prepareStatement()创建一编译预处理语句对象,可以向数据库发送带有参数的SQL语句。该类有一组setXXX方法,用设置参数值。这些参数被传送到数据库,预处理语句被执行。这个过程类似于给函数传递参数之后执行函数,完成预期的处理。使用PreparedStatement与使用Statement相比较有较高的效率,关于这一点详
11、见后面相关部分的阐述。 PreparedStatement ps; ResultSet rs=null; String query=select name,age,addr from xsda where addr = ?; ps=con.prepareStatement(query); ps.setString(1,hei); rs=ps.executeQuery();l (3)CallableStatement类的方法prepareCall()可用于创建对象,该对象用于向数据库发送一调用某存储过程的SQL语句。prepareCall()和prepareStatement()一样,所创建的语
12、句允许带有参数,用setXXX()设置输入参数,即IN参数,同时需接收和处理OUT参数、INOUT参数以及存储过程的返回值,概要说明其使用方法的语句例子如下: CallableStatement cstmt; ResultSet rs; cstmt = con.prepareCall(?=call stat(?,?); /stat是一存储过程的名字,它有两个参数,且有返回值 cstmt.setString(2,”Java Programming Language”); rs = cstmt.executeQuery();5检索结果检索结果数据库执行传送到的SQL语句,结果有多种存储位置,这与所
13、执行的语句有关。以查询语句select为例,其结果需返回到程序中一结果集对象,即前面语句例子中的ResultSet之对象rs。rs可看作是一个表子集,有若干行和若干列,行列的具体数量与查询条件及满足查询条件的记录数有关。要浏览该表内容可以借助ResultSet类的相关方法完成。例如行指针移动方法rs.next()和取列内容的方法rs.getXXX()等。若是执行数据更新语句update,则返回的是成功进行更新的数据库记录行数,所以,检索结果操作要依程序的具体内容而定。 6关闭连接关闭连接 完成对数据库得操作之后应关闭与常用数据库的连接。关闭连接使用close()方法。格式如下: con.clo
14、se();2.1.4 JDBC常用API JDBC API提供的类和接口是在java.sql包中定义的。1DriverManager类类DriverManager类的常用方法:1)static void deregisterDriver(Driver driver)方法,从DriverManager的列表中删除一个驱动程序。2)static Connection getConnection(String url)方法,建立到给定数据库URL的连接。3)static Connection getConnection(String url, Properties info)方法,用给定的数据库 U
15、RL和相关信息(用户名、用户密码等属性)来创建一个连接。4)static Connection getConnection(String url, String user, String password)方法,按给定的数据库 URL、用户名和用户密码创建一个连接。 5)static Driver getDriver(String url)方法,查找给定URL下的驱动程序。6)static EnumerationgetDrivers()方法,获得当前调用方可以访问的所有已加载 JDBC 驱动程序的 Enumeration。7)static int getLoginTimeout()方法,获得驱
16、动程序连接到某一数据库时可以等待的最长时间,以秒为单位。8)static PrintWriter getLogWriter()方法,检索记录写入器。9)static void println(String message) 方法,将一条消息打印到当前JDBC记录流中。10)static void registerDriver(Driver driver) 方法,向DriverManager注册给定驱动程序。2Connection类类Connection类有如下常量:1)static int TRANSACTION_NONE指示不支持事务。2)static int TRANSACTION_REA
17、D_UNCOMMITTED说明一个事务在提交前其变化 对于其他事务而言是可见的。这样可能发生脏读 (dirty read)、不可重复读(unrepeated read)和虚读 (phantom read) 。3)static int TRANSACTION_READ_COMMITTED说明读取未提交的数据是不允许的。防止发生脏读的情况,但不可重复读和虚读仍有可能发生。4)static int TRANSACTION_REPEATABLE_READ说明事务保证能够再次读取相同的数据而不会失败,但虚读有可能发生。5)static int TRANSACTION_SERIALIZABLE指示防止发生
18、脏读、不可重复读和虚读的常量。Connection类的常用方法:1)void clearWarnings()方法,清除此Connction对象报告的所有警告。2)void close()方法,断开此Connction对象和数据库的连接,而不是等待它们被自动释放。3)void commit()方法,使自从上一次提交/回滚以来进行的所有更改成为持久更改,并释放此 Connction 对象当前保存的所有数据库锁定。4)Statement createStatement()方法,创建一个Statement对象,用来将SQL语句发送到数据库。5)Statement createStatement(int
19、 resultSetType, int resultSetConcurrency) 方法,创建一个 Statement对象,该对象将生成具有给定类型和并发性的ResultSet对象。6)Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) 方法,创建一个Statement对象,该对象将生成具有给定类型、并发性和可保存性的ResultSet对象。 3Statement类类 Statement类的常用方法包括:1)void addBatch(String sq
20、l) 方法,将给定的SQL命令添加到此Statement对象的当前命令列表中。2)void clearBatch()方法,清空此Statement对象的当前SQL命令列表。3)void close()方法,立即释放此Statement对象的数据库和JDBC资源,而不是等待该对象自动关闭时发生此操作。4)boolean execute(String sql)方法,执行给定的SQL语句,该语句可能返回多个结果。5)int executeBatch()方法,将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。6)ResultSet executeQuery(String s
21、ql) 方法,执行给定的SQL语句,该语句返回单个 ResultSet对象。4PreparedStatement类类1)void addBatch()方法,将一组参数添加到此PreparedStatement对象的批处理命令中。2)boolean execute()方法,在此PreparedStatement对象中执行 SQL 语句,该语句可以是任何种类的 SQL 语句。3)ResultSet executeQuery()方法,在此PreparedStatement对象中执行 SQL 查询,并返回该查询生成的ResultSet对象。 4)int executeUpdate()方法,在此Prep
22、aredStatement对象中执行 SQL 语句,该语句必须是一个 SQL INSERT、UPDATE 或 DELETE 语句;或者是一个什么都不返回的 SQL 语句,比如 DDL 语句。5)ResultSetMetaDatagetMetaData()方法,检索包含有关 ResultSet 对象的列消息的 ResultSetMetaData 对象,ResultSet 对象将在执行此PreparedStatement对象时返回。6)ParameterMetaData getParameterMetaData()方法,检索此PreparedStatement对象的参数的编号、类型和属性。5Cal
23、lableStatement类类 CallableStatement类的方法主要有三种,设置参数的系列set方法和获取参数的系列get方法以及注册输出参数方法。下面分别示例说明之。1)boolean getBoolean(int parameterIndex)方法,以Java编程语言中boolean值的形式检索指定的JDBC BIT参数的值。2)boolean getBoolean(String parameterName)方法,以 Java 编程语言中boolean值的形式检索JDBC BIT参数的值。3)byte getByte(int parameterIndex)方法,以Java编程语
24、言中byte的形式检索指定的 JDBC TINYINT参数的值。4)short getShort(int parameterIndex)方法,以Java编程语言中short值的形式检索指定的JDBC SMALLINT参数的值。5)String getString(int parameterIndex)方法,以Java编程语言中String的形式检索指定的JDBC CHAR、VARCHAR或LONGVARCHAR参数的值。6)void registerOutParameter(int parameterIndex, int sqlType)方法,以parameterIndex为参数顺序位置将OU
25、T参数注册为 JDBC 类型sqlType。必须在执行存储过程之前调用此方法。由sqlType指定的OUT参数的JDBC类型确定必须用于get方法来读取该参数值的Java 类型。这种registerOutParameter应该在参数是JDBC类型NUMERIC或DECIMAL时使用。6ResultSet类类该类的几个常量的作用如下:1)static int CLOSE_CURSORS_AT_COMMIT,该常量指示调用 Cmit 方法时应该关闭ResultSet对象。2)static int CONCUR_READ_ONLY,该常量指示不可以更新的ResultSet对象的并发模式。3)stat
26、ic int CONCUR_UPDATABLE,该常量指示可以更新的ResultSet对象的并发模式。4)static int FETCH_FORWARD,该常量指示将按正向(即从第一个到最后一个)处理结果集中的行。5)static int FETCH_REVERSE,该常量指示将按反向(即从最后一个到第一个)处理结果集中的行处理。6)static int FETCH_UNKNOWN,该常量指示结果集中的行的处理顺序未知。7)static int HOLD_CURSORS_OVER_COMMIT,该常量指示调用Cmit 方法时不应关闭对象。8)static int TYPE_FORWARD_O
27、NLY,该常量指示指针只能向前移动的ResultSet对象的类型。10)static int TYPE_SCROLL_INSENSITIVE,该常量指示可滚动但通常不受其他的更改影响的ResultSet对象的类型。11)static int TYPE_SCROLL_SENSITIVE,该常量指示可滚动并且通常受其他的更改影响的ResultSet对象的类型。ResultSet类的方法按其功能可以分为二类,即指针移动方法和数据操作方法。这里仅举例说明这两类方法的功能。1)boolean absolute(int row)方法,将指针移动到此ResultSet对象的给定行编号。2)void afte
28、rLast()方法,将指针移动到此ResultSet对象的末尾,正好位于最后一行之后。3)void beforeFirst()方法,将指针移动到此ResultSet对象的开头,正好位于第一行之前。4)boolean first()方法,将指针移动到此ResultSet对象的第一行。5)boolean isAfterLast()方法,检索指针是否位于此ResultSet对象的最后一行之后。6)boolean isBeforeFirst()方法,检索指针是否位于此ResultSet对象的第一行之前。7)boolean isFirst()方法,检索指针是否位于此ResultSet对象的第一行。8)b
29、oolean isLast()方法,检索指针是否位于此ResultSet对象的最后一行。9)boolean last()方法,将指针移动到此ResultSet对象的最后一行。10)void moveToCurrentRow()方法,将指针移动到记住的指针位置,通常为当前行。11)void moveToInsertRow()方法,将指针移动到插入行。将指针置于插入行上时,当前的指针位置会被记住。插入行是一个与可更新结果集相关联的特殊行。它实际上是一个缓冲区,在将行插入到结果集前可以通过调用更新方法在其中构造新行。当指针位于插入行上时,仅能调用更新方法、获取方法以及insertRow方法。每次在调
30、用insertRow之前调用此方法时,必须为结果集中的所有列分配值。在对列值调用获取方法之前,必须调用更新方法。12)boolean next()方法,将指针从当前位置下移一行。ResultSet指针最初位于第一行之前;第一次调用next 方法使第一行成为当前行;第二次调用使第二行成为当前行,依此类推。如果开启了对当前行的输入流,则调用next方法将隐式关闭它。读取新行时,将清除ResultSet对象的警告链。 7Date类类 java.sql.Date与java.util.Date配合使用可以方便地处理应用程序中的日期型数据。下面的代码段可以对此做简要说明: Date d1 = new Da
31、te(); /d1为当前日期,某学生今日在图书馆借阅图书 int maxDays = 60;/一本书的规定借阅天数60天 Date d2 = new Date(d1.getTime()+60*24*60*60*1000); /d2为应还书日期若要与数据库交互,例如将该日期写入数据库相应字段,需借助java.sql.Date: rs.moveToInsertRow(); java.sql.Date d3 = new java.sql.Date(d2.getTime); rs.updateDate(“应还日期”,d3);/将所借之书的应还日期写入数据库 rs.insertRow();8元数据类元数
32、据类Java定义的元数据(MetaData)有以下三种:DatabaseMetadata用于获得关于数据库和数据表的信息。ResultSetMetaData用于获得关于结果集的信息。ParameterMetaData用于获得预处理语句预处理语句对象参数的类型和属性信息。2.1.5 数据库连接范例1连接连接Oracle数据库(用数据库(用thin模式)模式) Class.forName(“oracle.jdbc.driver.OracleDriver”); String url = “jdbc:oracle:thin:localhost:1521:db”; Connection con = Dr
33、iverManager.getConnection(url,user,password); Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CUNCUR_UPDATABLE);2连接连接MySQL数据库数据库 Class.forName(“com.mysql.jdbc.Driver”); String url = “jdbc:mysql:/localhost:3306/db”; Connection con = DriverManager.getConnection(url,user,
34、password); Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CUNCUR_UPDATABLE);3连接连接Sql Server数据库数据库 Class.forName(“com.microsoft.jdbc.sqlserver.SQLServerDriver”); String url = “jdbc:microsoft:sqlserver:/localhost:1433;DatabaseName=db”; String user = ”sa”; String passwor
35、d = ”; Connection con = DriverManager.getConnection(url,user,password); Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CUNCUR_UPDATABLE);2.2 数据库基本操作2.2.1 数据插入操作Insert语句格式如下: INSERT INTO (字段名,字段名) VALUES(常量,常量)由于字段的类型不同,在values中的值的写法要求也不同。概括起来说有如下几点:(1)数值型字段,可以直接写数值;(2
36、)字符型字段,其值要加单引号。(3)日期型字段,其值要加单引号,同时还要注意年、月、日的次序。例如,要向表member中插入一行数据的SQL语句是:INSERT INTO member (name,age,sex,wage,addr) VALUES (LiMing,40,男,4500,北京市) INSERT INTO emp(empno,hiredate)VALUES (8888,to_date(2002-09-08,YYYY-MM-DD)向表中插入NULL值需要满足以下几点:(1)插入NULL的列在表中的定义不能为NOT NULL。(2)插入NULL的列在表的定义不能为主键或作为另外表的外键
37、。(3)插入NULL的列在表的定义里不能有唯一的约束。对很多数据库而言,对数据的插入、删除和更新操作都有两种可选的操作模式:直接使用SQL语句插入(或更新、删除)模式和通过可更新的结果集对象间接插入(或更新、删除)。且记,我们在创建语句对象时用下面的形式: Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CUNCUR_UPDATABLE);其中,参数ResultSet.CUNCUR_UPDATABLE的作用正是为了使该语句生成的结果对象是可更新结果集,它可被用来插入、更新、删除记录内容
38、。 下面的程序段说明了如何利用可更新结果集进行数据插入: rs.moveToInsertRow(); rs.updateString(name,LiMing ); rs.updateInt(age,40); rs.updateString(sex,男); rs.updateInt(wage,50000); rs.updateString(addr,北京市); rs.insertRow();试比较若为交互操作引入变量在上面的操作中和在SQL INSERT语句中的情形,何者更方便是一目了然的。看看下面的SQL INSERT语句,体会一下恼人的拼串过程: String sqlins = INSERT
39、 INTO students values( + sno + , +name + , + sex + , + birthday + , + , + department + ) ;2.2.2 数据删除操作Delete语句的格式为: DELETE FROM WHERE 例如: DELETE FROM table1 WHERE No = 7658从表table1中删除一条记录,其字段No的值为7658。使用可更新结果集的删除操作,参见下面的代码段:stmt = con.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR
40、_UPDADABLE);con.setAutoCommit(false); String sqlst = “select * from member”; rs = stmt.executeQuery(sqlst); rs.relative(4);/移动到第4条记录 rs.deleteRow();/从结果集和底层数据库删除该记录 mit();2.2.3 数据更新操作数据更新语句的命令格式为 : UPDATE SET colume_name = xxx WHERE 例如语句: UPDATE EMP SET JOB=MANAGER WHERE NAME=MATIN对数据表EMP中姓名为MATIN的职
41、工数据进行了修改,将其工作名称改为MANAGER。向数据库发送数据更新的SQL语句是通过调用方法executeUpdate()完成的:String ss=update xsda set age=age+1 where name=yang ; stmt.executeUpdate(ss);下面的代码说明使用可更新结果集进行更新操作的方法。 rs=stmt.executeQuery(select * from member where age=16); rs.first() ; rs.updateInt(wage,3000); rs.updateRow(); rs.next(); rs.updat
42、eInt(wage,4000); rs.updateRow(); rs.next(); rs.updateString(addr,上海市); rs.updateRow();上面的代码对连续3条记录的wage字段和addr字段值进行了更新操作。2.2.4 数据查询操作查询语句的语句格式如下: SELECT DISTINCT column1,column2, FROM tablename WHERE conditions GROUP BY conditionsHAVING conditions ORDER BY conditionsASC/DESC; 说明:SELECT子句用于指定检索数据库中的哪
43、些列,若要检索所有列可以不必列出所有列名,只用*表示即可。FROM子句用于指定从哪一个表或者视图中检索数据。选项DISTINCT指明显式结果不重复,无此选项则显示所有记录可能重复。例如下面的语句只显示姓名不同的记录: select distinct Name from person;WHERE子句用于指定查询条件,若condition条件表达式的值为TRUE,则检索相应的行,若条件表达式的值为FALSE,则不会检索该行数据。GROUP BY指出记录分组的条件,例如进行分组统计。HAVING则是用于限制分组统计的结果。例如统计emp表中不同部门(depno)不同岗位(job)的平均工资(AVG(
44、sal)大于3000的所有记录的语句如下: SELECT depno,job,AVG(sal) FROM emp GROUP BY depno,job HAVING AVG(sal)3000;注意:HAVING子句必须跟在GROUP BY子句的后面。ORDER BY子句指出查询结果排序显示,可为升序(ASC)或可为降序(DESC)排列。2.2.5 事务处理所谓事务,概指一系列的数据库操作,这些操作要么全做,要么全不做,是一个不可分割的工作单元,也可以说是数据库应用程序中的一个基本逻辑单元。它可能是一条SQL语句、一组SQL语句或者一个完整的程序。这体现的是事务的原子性需求,对事务还有其他的需求
45、如一致性、隔离性、持久性 。JDBC事务处理可采用隔离级别控制数据读取操作。JDBC支持5个隔离级别设置,其名字和含义如下所示:static int TRANSACTION_NONE 不支持事务static int TRANSACTION_READ_COMMITED 脏读、不可重复读、错误读取可能出现static int TRANSACTION_READ_UNCOMMITED 禁止脏读,不可重复读、错误读取可能出现static int TRANSACTION_REPEATABLE_READ 禁止脏读、不可重复读,错误读取可能出现static int TRANSACTION_SERIALIZAB
46、LE 禁止脏读、不可重复读、错误读取。上面的5个常量是Connection中提供的。同样Connection提供了方法进行隔离级别设置: setTransactionIsolation(Connection. TRANSACTION_REPEATABLE_READ)一个事务也许包含几个任务,正象超市里面完成一个事务也要包括几个任务一样。超市里的一个事务对应于一次消费活动的全过程。它是由若干个任务构成的。确定购买项目,登记每个项目,然后计算总额,之后支付。只有当每个任务结束后,事务才结束。如果其中的一个任务失败,则事务失败,前面完成的任务也要恢复。这是基本性质。Connection中下面三个方法
47、完成基本的事务管理:1)setAutoCommit(boolean true/false)方法,设置自动提交属性AutoCommit,默认为true。2)rollback()方法,回滚事务。3)commit()方法,事务提交。在调用了commit()方法之后,所有为这个事务创建的结果集对象都被关闭了,除非通过createStatement()方法传递了参数:HOLD_CURSORS_OVER_COMMIT其功能相对的另一个参数为:CLOSE_CURSORS_AT_COMMIT在commit()方法被调用时关闭ResultSet对象。事务中若包含多个任务,当事务失败时,也许其中部分任务不需要被回
48、滚,例如处理一个订单要完成3个任务:更新消费者帐户表,定单插入到待处理的定单表,给消费者发一确认电子邮件。如果上述3个任务中完成了前2个只是最后一个因为邮件服务器掉线而未完成,那么不需要对整个事务回滚。如何处理有数量选择与控制的回滚操作?我们需要引进保存点(savepoint)来控制回滚的数量。 Jdbc3.0支持保存点的操作。所谓保存点,就是对事务的某些子任务设置符号标识,用以为回滚操作提供位置指示。关于保存点的方法主要有以下三个:(1)setSavepoint(“保存点名称”)方法,在某子任务前设置一保存点。(2)releaseSavepoint(“保存点名称”)方法,释放一指定名称的保存
49、点。(3)rollback(“保存点名称”)方法,指示事务回滚到指定的保存点。2.3 数据库存取优化2.3.1 常用技术(1)优化SQL语句的执行效率(2)定义和调用存储过程(3)采用编译预处理(4)采用数据库连接池技术(5)选择合适的JDBC驱动程序(6)优化建立的连接2.3.2 编译预处理首先了解一下PreparedStatement这个类 。PreparedStatement是Statement的一个子类。PreparedStatement类与Statement类的一个重要区别是:用Statement定义的语句是一个功能明确而具体的语句,而用PreparedStatement类定义的SQ
50、L语句中则包含有一个或多个问号(“?”)占位符,它们对应于多个IN参数。带着占位符的SQL语句被编译,而在后续执行过程中,这些占位符需要用setXXX方法设置为具体的IN参数值,这些语句发送至数据库获得执行。 下面给出若干编译预处理语句例子说明PreparedStatement的用法:首先创建对象:PreparedStatement pstmt = con.prepareStatement(“update table1 set x=? where y=?”);在对象pstmt中包含了语句“update table1 set x=? where y=?”,该语句被发送到DBMS进行编译预处理,为