`
xiao_yi
  • 浏览: 405415 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JDBC基础(六)

阅读更多

使用连接

有时您要从两张或多张表中检索数据。例如,假设Coffee Break的老板想查询从Acme公司购买的咖啡,这就涉及COFFEES表和尚未创建的SUPPLIERS表。这就是需要使用连接的一种情形。连接是一种数据库操作,它用两张或多张表所共享的信息将表彼此联系起来。在示例数据库中,COFFEES表和SUPPLIERS表都有SUP_ID列,该列可用于连接这两张表。

 

在继续学习之前,我们需要创建SUPPLIERS表,并在其中输入一些数据。

下面的代码创建SUPPLIERS表:

String createSUPPLIERS = "create table SUPPLIERS " +  
			 "(SUP_ID INTEGER, SUP_NAME VARCHAR(40), " + 
			 "STREET VARCHAR(40), CITY VARCHAR(20), " +
			 "STATE CHAR(2), ZIP CHAR(5))";
stmt.executeUpdate(createSUPPLIERS);

下面的代码在SUPPLIERS表中插入3个供应商: 

stmt.executeUpdate("insert into SUPPLIERS values (101, " +
    "'Acme, Inc.', '99 Market Street', 'Groundsville', " + "'CA', '95199'");
stmt.executeUpdate("Insert into SUPPLIERS values (49," +
    "'Superior Coffee', '1 Party Place', 'Mendocino', 'CA', " + "'95460'");
stmt.executeUpdate("Insert into SUPPLIERS values (150, " + 
    "'The High Ground', '100 Coffee Lane', 'Meadows', 'CA', " + "'93966'");

下面的代码检出了整张表,让您看到SUPPLIERS表中的内容:

ResultSet rs = stmt.executeQuery("select * from SUPPLIERS");

这行代码执行后结果集如下:

SUP_ID ------ 101 49 150

SUP_NAME

STREET

CITY

STATE

ZIP

-------------

-------------

-----------

-----

-----

Acme, Inc.

99 Market Street

Groundsville

CA

95199

Superior Coffee

1 Party Place

Mendocino

CA

95460

The High Ground

100 Coffee Lane

Meadows

CA

93966

现在有了COFFEES表和SUPPLIERS表,可以继续前面的查询,即查询老板从特定供应商那里购买的咖啡。供应商名称在SUPPLIERS表中,咖啡名称在COFFEES表中。因为两张表中都有SUP_ID列,所以这一列可用于连接两张表。但您要有区分所引用的SUP_ID列的方法。这是通过列名加上表名作为前缀来实现的(如“COFFEES.SUP_ID”表示所引用的是COFFEES表中的SUP_ID列 )。下面的代码(其中stmt是一个Statement对象)将检出从Acme公司购买的咖啡:

String query = "
SELECT COFFEES.COF_NAME " +
   "FROM COFFEES, SUPPLIERS " +
   "WHERE SUPPLIERS.SUP_NAME LIKE 'Acme, Inc.' " +
   "and SUPPLIERS.SUP_ID = COFFEES.SUP_ID";

ResultSet rs = stmt.executeQuery(query);
System.out.println("Coffees bought from Acme, Inc.: ");
while (rs.next()) {
    String coffeeName = rs.getString("COF_NAME");
    System.out.println("     " + coffeeName);
}

上面的代码执行后将输出:

Coffees bought from Acme, Inc.:
     Colombian
     Colombian_Decaf

 

使用事务

有时您想让一条语句只有在另一条语句也成功执行时才产生效果。例如,Coffee Break老板在更新每周销售量时也想更新迄今销售量。但他不期望一列更新而另外一列没有更新;否则数据将不一致。确保两列全部更新或全部不更新的方法就是使用事务。一个事务是作为一个单元执行的一组语句(一条或多条语句),因此它们要么全部执行,要么全部不执行。

 

禁用自动提交模式

当连接创建时,它处在自动提交模式。这表明每条SQL语句作为一个事务,语句执行后马上提交(更确切地说,默认情况下SQL语句是在执行完成时提交,而不是在执行时提交。当一条语句的所有结果集和更新数目已检出时,这条语句就执行完毕了。但在多数场合,一条语句执行完就结束了,因此也就提交了)。 

要让两条或更多条语句组成一个事务就要禁用自动提交模式。下面的代码例示了这一操作(其中con为活动连接):

con.setAutoCommit(false);

提交事务

一旦禁用了自动提交模式,就没有SQL语句会提交了,除非您显式调用commit方法。在前一次调用commit方法后执行的所有语句将包含在当前事务中,这些语句将作为一个单元进行提交。下面的代码(其中con是一个活动连接)例示了一个事务:

con.setAutoCommit(false);
PreparedStatement updateSales = con.prepareStatement(
    "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?");
updateSales.setInt(1, 50);
updateSales.setString(2, "Colombian");
updateSales.executeUpdate();
PreparedStatement updateTotal = con.prepareStatement(
    "UPDATE COFFEES SET TOTAL = TOTAL + ? WHERE COF_NAME LIKE ?");
updateTotal.setInt(1, 50);
updateTotal.setString(2, "Colombian");
updateTotal.executeUpdate();
con.commit();
con.setAutoCommit(true);

在本例中,连接con的自动提交模式被禁用了,这表明当调用commit方法时,updateSales和updateTotal这两个预备语句将一起提交。一旦调用了commit方法(启用自动提交模式时是自动调用该方法,禁用自动提交模式时要显式调用该方法),事务中的语句产生的变更将变为永久的。在本例中,这表明Colombian咖啡的SALES和TOTAL列已变为50(如果先前的TOTAL是0),它们将维持这个值直到另一条更新语句改变它们。TransactionPairs.java例示了类似的事务,但使用for循环为updateSales和updateTotal的setXXX方法提供数值。

前面例子的最后一行启用了自动提交模式,这表明每条语句执行完毕将再次自动提交。您将返回到默认状态,在这种状态下不必亲自调用commit方法。禁用自动提交模式是可取的,除非您想处在事务模式。在这种模式下可避免持有多条语句的数据库锁,但增加了与其他用户发生冲突的可能性。

使用事务保持数据完整性

除了将语句组成一个单元一起执行外,事务还有助于保持表中数据的完整性。例如,假设一个员工计划在COFFEES表中输入新的咖啡价格,但由于其他事情耽搁了几天。期间价格上涨了,今天老板正在输入更高的价格。就在老板要更新那张表时,那位员工回来输入已过时的价格。在插入过时价格后,那位员工意识到这些价格不再有效了,就调用Connection方法rollback来取消操作(rollback方法取消一个事务,将数据还原到试图变更之前)。此时老板正在执行SELECT语句并输出新的价格。在这种情形下,老板就可能输出了不正确的价格,这些价格就被还原到以前的值了。

这种情形可通过使用事务来避免。如果DBMS支持事务(几乎所有DBMS都支持),它将提供一些级别的冲突保护,两个用户同时访问数据会引起冲突。

为避免事务期间的冲突,DBMS将使用锁——阻止其他人访问事务正在访问的数据的一种机制(在自动提交模式下,每条语句就是一个事务,锁只由一条语句持有)。一旦加了锁,它将维持有效,直到事务提交或回滚。例如,DBMS可能锁住表中一行,直到提交对它的更新。这种锁可防止用户脏读,即在数据变为永久前读取(访问没有提交的更新数据就是脏读,因为数据可能回滚到原来的值。如果读取了随后回滚的数据,那就是读取了无效的数据)。

加锁机制由事务隔离级别(Isolatoin Level)决定,事务隔离级别可从完全不支持事务一直上升到支持强加了非常严格的访问规则的事务。

JDBC事务隔离级别的一个例子是TRANSACTION_READ_COMMITTED,它不允许访问没有提交的数据。换言之,如果事务隔离级别设为TRANSACTION_READ_COMMITTED,DBMS将不允许脏读出现。Connection接口包括了5个值,代表JDBC中可用的事务隔离级别。

一般不必设置事务隔离级别,可使用DBMS默认的事务隔离级别。JDBC允许查出DMBS中设置的事务隔离级别(使用Connection方法getTransactionIsolation),也允许设置另外的事务隔离级别(使用Connection方法setTransactionIsolation)。但是一定要记住,虽然JDBC允许设置事务隔离级别,但是除非得到所使用的驱动程序和DBMS的支持,否则设置也没有用。

何时调用rollback方法

如前所述,调用rollback方法可取消一个事务,将修改的任何数据返还到以前的值。如果在执行一个事务中的一条或多条语句时得到了SQLException,就应该调用rollback方法取消事务,从头开始整个事务。这是确信什么已提交和什么未提交的惟一方法。捕获了SQLException表明出错了,但它并不能说明什么提交了或什么未提交。因为您不能相信什么都没提交的事实,所以调用rollback方法是确保什么都没提交的惟一方法。

Transaction.java例示了一个事务,并包含一个调用rollback方法的catch块。在这里确实没有必要调用rollback,但程序调用了rollback,这主要为了说明rollback的使用。如果程序继续执行,并使用了事务的结果,就有必要在catch块中调用rollback,以避免可能使用不正确的数据。

评论

相关推荐

    踩踩踩JDBC六大步骤

    ### JDBC六大步骤详解 在Java开发中,JDBC(Java Database Connectivity)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供...通过以上六个步骤,我们可以基本掌握如何使用JDBC进行数据库操作的基础流程。

    自学jdbc心得体会

    六、JDBC基本方法 * DriverManager:如果有多个驱动可用的话,DriverManager会选择其中一个。 * Driver:可以选择固定的驱动。 七、JDBC配置和应用心得 * 在使用JDBC之前,需要加载驱动程序。 * 需要注意JDBC的...

    JDBC基础教程之概述.txt

    ### JDBC基础教程之概述 #### 一、JDBC简介与概念理解 JDBC(Java Database Connectivity)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC的...

    JDBC 入门电子书.zip

    **JDBC 入门知识详解** ...综上所述,JDBC是Java与数据库交互的基础,理解其工作原理和最佳实践对于任何Java开发者来说都至关重要。通过深入学习,我们可以更有效地构建健壮且高效的数据库应用程序。

    JDBC数据库编程实验

    (1)熟练掌握JDBC操作数据库的整个过程; (2)利用预处理语句操作数据库; (3)掌握可滚动和可更新的结果集的基本操作方法; (4)理解JDBC中实现事务处理的基本方法; (5)理解数据库连接池的基本原理和思想,...

    jdbc 课件.doc

    **JDBC基础应用详解** **一、JDBC概述** JDBC(Java Database Connectivity)是Java语言与各种数据库之间通信的标准接口,由Sun Microsystems公司开发并引入Java平台,它允许Java程序通过标准API来访问和操作...

    JDBC基础教程之语句.doc

    ### JDBC基础教程之语句详解 #### 一、概述与Statement对象 JDBC(Java Database Connectivity)是一种用于执行SQL语句的Java API,允许Java应用程序连接到几乎所有的关系型数据库管理系统。本文档主要介绍了JDBC...

    JDBC基础教程之PreparedStatement.doc

    ### JDBC基础教程之PreparedStatement知识点详解 #### 一、概述 `PreparedStatement`是Java数据库连接(JDBC)API中的一种重要接口,它继承自`Statement`接口,并在其基础上进行了扩展和优化。`PreparedStatement`...

    jdbc入门至精通

    本文将从基础概念出发,逐步深入,帮助读者从入门到精通JDBC。 **第二节 jdbc的概念** 2.1 **概念** JDBC是Java API(应用程序接口),它为Java程序员提供了一组接口和类,用于与各种数据库进行交互,实现数据的增...

    JDBC基础教程之CallableStatement.doc

    ### JDBC基础教程之CallableStatement详解 #### 一、概述 在数据库编程中,为了提高代码的复用性和执行效率,通常会使用存储过程。存储过程是预编译并存储在数据库中的SQL语句集合,可以接受输入参数并返回输出...

    发个基础jdbc

    **标题:“发个基础jdbc”** 在Java编程中,JDBC(Java Database Connectivity)是连接Java应用程序和数据库的标准接口。这个“基础jdbc”的主题涵盖了如何使用JDBC进行基本的数据库操作,包括数据库连接、SQL语句...

    JDBC资料文档第一部分

    1. **java.sql**:这是JDBC的基础包,包含了用于基本数据库编程的服务,例如创建连接、执行语句、准备语句和运行批处理查询等。此外,还有一些高级处理,如批处理更新、事务隔离和可滚动结果集等。 2. **javax.sql**...

    Java Database Programming with JDBC

    总的来说,《Java Database Programming with JDBC》是一本全面介绍Java数据库编程的书籍,涵盖了从基础的SQL语法到高级的JDBC应用,对于希望使用Java进行数据库开发的程序员来说,是一份宝贵的资源。

    Java数据库接口JDBC入门基础讲座

    六、JDBC与ORM框架的关系 虽然JDBC提供了基础的数据库访问功能,但在实际开发中,人们常常使用ORM(Object-Relational Mapping)框架如Hibernate、MyBatis等,它们简化了JDBC的使用,提供了更加面向对象的数据库操作...

    Jdbc实用教程

    总结,JDBC是Java开发中的基础工具,通过理解和掌握其核心概念和最佳实践,开发者可以更高效、安全地实现数据库操作。本教程详细阐述了JDBC的各个方面,包括API、连接步骤、事务管理以及优化策略,旨在帮助学习者...

    JDBC代码

    一、JDBC基础 1. JDBC驱动:在Java程序中使用JDBC之前,必须先安装并加载对应的JDBC驱动。根据驱动的实现方式,JDBC驱动分为四种类型:Type 1、Type 2、Type 3和Type 4,其中Type 4是纯Java实现,性能最优。 2. ...

    jdbc课程笔记教案.docx

    【JDBC 的六大步骤】 1. 加载驱动:`Class.forName("com.mysql.jdbc.Driver")` 2. 创建连接:`Connection conn = DriverManager.getConnection(url, username, password)` 3. 创建Statement对象:`Statement stmt =...

    一头扎进JDBC视频教程源码

    1. **第一讲:JDBC基础** - JDBC API简介:了解JDBC的基本概念,如DriverManager、Connection、Statement和ResultSet等。 - 数据库连接:如何加载数据库驱动,建立数据库连接。 - SQL语句执行:使用Statement对象...

    一份详尽的jdbc教材

    3. **易用性**:相比C语言为基础的ODBC,JDBC更易于理解和使用,尤其是在面向对象编程方面。 #### 五、JDBC的API接口 JDBC主要包括两个层面的接口: 1. **JDBC API**:面向开发者的API,包括`java.sql.Connection`...

    JDBC学习笔记总结,可以看看

    创建一个基本的JDBC应用需要六个步骤: 1. 注册一个driver 2. 建立一个到数据库的连接 3. 创建一个statement 4. 执行SQL语句 5. 处理结果 6. 关闭JDBC对象 注册一个Driver 注册一个driver需要使用类loader装载、...

Global site tag (gtag.js) - Google Analytics