`
Lewiss
  • 浏览: 19650 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

JDBC Glean

    博客分类:
  • J2SE
阅读更多
JDBC 各组件调用关系



JDBC 中常用的、关键的几个类:
DriverManager dm = null;
		Connection conn = null;
		Statement stmt = null;
		PreparedStatement pstmt = null;
		CallableStatement cstmt = null;
		ResultSet rs = null;



DriverManager

管理所有注册的数据驱动。JDBC 规定,当数据驱动(Driver)被加载时,它必须向 DriverManager 注册。所以,当用 Class.forName(driver) 加载数据库驱动时,driver 就已经注册到 DriverManager 中了。如 mysql 的 Driver 类:

package com.mysql.jdbc;

import java.sql.SQLException;

/**
 * The Java SQL framework allows for multiple database drivers. Each driver
 * should supply a class that implements the Driver interface
 * 
 * <p>
 * The DriverManager will try to load as many drivers as it can find and then
 * for any given connection request, it will ask each driver in turn to try to
 * connect to the target URL.
 * 
 * <p>
 * It is strongly recommended that each Driver class should be small and
 * standalone so that the Driver class can be loaded and queried without
 * bringing in vast quantities of supporting code.
 * 
 * <p>
 * When a Driver class is loaded, it should create an instance of itself and
 * register it with the DriverManager. This means that a user can load and
 * register a driver by doing Class.forName("foo.bah.Driver")
 * 
 * @see org.gjt.mm.mysql.Connection
 * @see java.sql.Driver
 * @author Mark Matthews
 * @version $Id$
 */
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
	// ~ Static fields/initializers
	// ---------------------------------------------

	//
	// Register ourselves with the DriverManager
	//
	static {
		try {
			java.sql.DriverManager.registerDriver(new Driver());
		} catch (SQLException E) {
			throw new RuntimeException("Can't register driver!");
		}
	}

	// ~ Constructors
	// -----------------------------------------------------------

	/**
	 * Construct a new driver and register it with DriverManager
	 * 
	 * @throws SQLException
	 *             if a database error occurs.
	 */
	public Driver() throws SQLException {
		// Required for Class.forName().newInstance()
	}
}



Connection

一个 Connection 实例代表一个到数据的连接。可以从 DriverManager 或 DataSource 中获得 Connection 实例。
对数据库的所有操作都是通过 Connection 提交到数据库的,Connection 的一次提交就是一次事务。在默认情况下,每执行一次 sql 语句,Connection 就自动提交,这也是最小的事务单位,所以就算本次操作失败了,也无需做 rollback,因为失败而数据没被持久化(或者说自动提交则自动回滚)。
当需要把多个 sql 操作作为一个原子操作室,就把它们放到同一个事务中,此时需要把 Connection 的自动提交关掉,当所有 sql 操作完后再进行提交,如果其中某个操作失败了,则 rollback 所有操作,如:
try {
			conn.setAutoCommit(false);
			stmt = conn.createStatement();
			stmt.executeUpdate("sql1");
			stmt.executeUpdate("sql2");
			stmt.executeUpdate("sql3");
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
			conn.rollback();
		} finally {
			stmt.close();
			conn.close();
		}


注意:Connection 可以设置 savepoint,当某个操作失败时,可以回滚到某个 savepoint,而不用回滚所有的 sql 操作,我想这就是嵌套事务实现的原理。如
Savepoint sp = null;
		try {
			conn.setAutoCommit(false);
			stmt = conn.createStatement();
			stmt.executeUpdate("sql1");
			stmt.executeUpdate("sql2");

			sp = conn.setSavepoint();
			stmt.executeUpdate("sql3");
			stmt.executeUpdate("sql4");
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
			conn.rollback(sp);
		} finally {
			stmt.close();
			conn.close();
		}


Connection 还可以获取数据库的元信息:DatabaseMetaData,包含表、视图等信息。


Statement,PreparedStatement,CallableStatement

Statement 和 PreparedStatement 的主要区别是:PreparedStatement 对 sql 语句做了优化,以在后面的执行过程中达到更快的速度。
但是注意:PreparedStatement 适用于某个 sql 语句被多次执行只是参数不同的情况,如果 PreparedStatement 只是被执行一两次,那么此时它的性能可能比不上 Statement,因为它在 sql 语句优化上付出了开销。
CallableStatement 用于调用数据库的存储过程。


ResultSet

ResultSet 实例表示某次 sql 执行返回的结果集,在数据库中反映为结果表(在数据库中,每次查询返回的结果都放在一个临时表中?)。
注意:对于不同的数据库驱动厂商,返回结果的方式有所不同。如 mysql 将所有结果一次性返回,而有些厂商则只返回一部分的数据,等到调用 rs.next() 的时候再去数据拿下一次的数据。
我们一般默认使用不可滚动、不可更新的结果集,在有需要的情况下,可以用以下方式创建 stmt以返回可滚动、可更新的结果集:
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
于是就可以对返回的结果集进行更新行、删除行、插入行等操作。
对于 ResultSet 的两个参数,有如下说明:

When creating a Statement object, you need to specify two arguments to the method
createStatement(). The first argument indicates the type of a ResultSet object and can be one of three constants:

• ResultSet.TYPE_FORWARD_ONLY: A constant indicating the type for a ResultSet object whose cursor may move only forward (creates a nonscrollable ResultSet object)

• ResultSet.TYPE_SCROLL_INSENSITIVE: A constant indicating the type for a ResultSet object that is scrollable but generally not sensitive to changes made by others

• ResultSet.TYPE_SCROLL_SENSITIVE: A constant indicating the type for a ResultSet object that is scrollable and generally sensitive to changes made by others

The second argument is one of two ResultSet constants for specifying whether a result set is read-only or writable/updatable:

• ResultSet.CONCUR_READ_ONLY: A constant indicating the concurrency mode for a ResultSet object that may not be updated

• ResultSet.CONCUR_UPDATABLE: A constant indicating the concurrency mode for a ResultSet object that may be updated

The important point to remember is that if you specify a ResultSet type, you must also specify whether it is read-only or writable/updatable.


一个事务之和唯一一个 Connection 实例关联。当事务 tr1 更新某表数据时,它会锁住该表,直到本次事务提交。在此期间,如果有事务 tr2 欲对同一个表做更新操作,那么 tr2 会阻塞,知道 tr1 提交完毕后,tr2 才能往下继续操作该表。


数据库支持表级、行级锁定,可用语句 sql … for update 进行行级锁定。


Date、Time、Timestamp

在 SQL 中,Date 只能存储日期,如:1999-9-9,Time 只能存储时间,如:23:59:59。如在 mysql 中,如果往 date 列存入值 1999-9-9 23:59:59,则 “23:59:59” 被自动截去,只存入“1999-9-9”,往 time 列存入值 1999-9-9 23:59:59,则 “1999-9-9” 被自动截去,只存入 “23:59:59”。在 mysql 中,可以用 datetime 存储日期和时间。


BLOB、CLOB

都是大字段,这两中类型的本质区别是,BLOB 大小写敏感,CLOB 大小写不敏感。如在 msql 中有以下 case:


可以看到在表 t_blob 中,field_blob 为 blob 类型,当我们把 t_blob 中的记录按field_blob 排序时,可以看到 “BBB”排在 “aaa”的前面,这是正确的,因为在 ascii 中 B 的值本来就小于 a ;但是再 t_clob 中,我们把 t_clob 中的记录按 field_clob 排序时,“aaa”是排在 “BBB” 前面的,因为 CLOB 类型大小写不敏感,在大小写不敏感的情况下,a 当然小于 b(B)。
  • 大小: 59.6 KB
  • 大小: 15 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics