JDBC API主要位于JDK中的java.sql包中(之后扩展的内容位于javax.sql包中),主要包括(斜体代表接口,需驱动程序提供者来具体实现):
- DriverManager:负责加载各种不同驱动程序(Driver),并根据不同的请求,向调用者返回相应的数据库连接(Connection)。
- Driver:驱动程序,会将自身加载到DriverManager中去,并处理相应的请求并返回相应的数据库连接(Connection)。
- Connection:数据库连接,负责与进行数据库间通讯,SQL执行以及事务处理都是在某个特定Connection环境中进行的。可以产生用以执行SQL的Statement。
- Statement:用以执行SQL查询和更新(针对静态SQL语句和单次执行)。
- PreparedStatement:用以执行包含动态参数的SQL查询和更新(在服务器端编译,允许重复执行以提高效率)。
- CallableStatement:用以调用数据库中的存储过程。
- SQLException:代表在数据库连接的创建和关闭和SQL语句的执行过程中发生了例外情况(即错误)。
数据类型的映射[编辑]
SQL类型 | Java类型 |
---|---|
CHAR | java.lang.String |
VARCHAR | java.lang.String |
LONGVARCHAR | java.lang.String |
NUMERIC | java.math.BigDecimal |
DECIMAL | java.math.BigDecimal |
BIT | boolean |
TINYINT | byte |
SMALLINT | short |
INTEGER | int |
BIGINT | long |
REAL | float |
FLOAT | double |
DOUBLE | double |
BINARY | byte[] |
VARBINARY | byte[] |
LONGVARBINARY | byte[] |
DATE | java.sql.Date |
TIME | java.sql.Time |
TIMESTAMP | java.sql.Timestamp |
BLOB | java.sql.Blob |
CLOB | java.sql.Clob |
Array | java.sql.Array |
REF | java.sql.Ref |
Struct | java.sql.Struct |
注:这种类型匹配不是强制性标准,特定的JDBC厂商可能会改变这种类型匹配。例如Oracle中的DATE类型是包含时分秒,而java.sql.Date仅仅支持年月日。
例子[编辑]
利用Class.forName()方法来加载JDBC驱动程序(Driver)至DriverManager:
Class.forName( "com.somejdbcvendor.TheirJdbcDriver" );
然后,从DriverManager中,通过JDBC URL,用户名,密码来获取相应的数据库连接(Connection):
Connection conn = DriverManager.getConnection( "jdbc:somejdbcvendor:other data needed by some jdbc vendor", // URL "myLogin", // 用户名 "myPassword" ); // 密码
不同的JDBC驱动程序的URL是不同的,它永远以“jdbc:”开始,但后面的内容依照驱动程序类型不同而各异。在获取Connection之后,便可以创建Statement用以执行SQL语句。下面是一个插入(INSERT)的例子:
Statement stmt = conn.createStatement(); stmt.executeUpdate( "INSERT INTO MyTable( name ) VALUES ( 'my name' ) " );
查询(SELECT)的结果存放于结果集(ResultSet)中,可以按照顺序依次访问:
Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( "SELECT * FROM MyTable" ); while ( rs.next() ) { int numColumns = rs.getMetaData().getColumnCount(); for ( int i = 1 ; i <= numColumns ; i++ ) { // 与大部分Java API中下标的使用方法不同,字段的下标从1开始 // 当然,还有其他很多的方式(ResultSet.getXXX())获取数据 System.out.println( "COLUMN " + i + " = " + rs.getObject(i) ); } } rs.close(); stmt.close();
但是,通常,Java程序员们更倾向于使用PreparedStatement。下面的例子使用上例中的conn对象:
PreparedStatement ps = null; ResultSet rs = null; try { ps = conn.prepareStatement( "SELECT i.*, j.* FROM Omega i, Zappa j WHERE i = ? AND j = ?" ); // 使用问号作为参数的标示 // 进行参数设置 // 与大部分Java API中下标的使用方法不同,字段的下标从1开始,1代表第一个问号 // 当然,还有其他很多针对不同类型的类似的PreparedStatement.setXXX()方法 ps.setString(1, "Poor Yorick"); ps.setInt(2, 8008); // 结果集 rs = ps.executeQuery(); while ( rs.next() ) { int numColumns = rs.getMetaData().getColumnCount(); for ( int i = 1 ; i <= numColumns ; i++ ) { // 与大部分Java API中下标的使用方法不同,字段的下标从1开始 // 当然,还有其他很多的方式(ResultSet.getXXX())获取数据 System.out.println( "COLUMN " + i + " = " + rs.getObject(i) ); } } catch (SQLException e) { // 异常处理 } finally { // 使用finally进行资源释放 try { rs.close(); ps.close(); } catch( SQLException e){} // 异常处理:忽略close()时的错误 }
如果数据库操作失败,JDBC将抛出一个SQLException。一般来说,此类异常很少能够恢复,唯一能做的就是尽可能详细的打印异常日记。推荐的做法是将SQLException翻译成应用程序领域相关的异常(非强制处理异常)并最终回滚数据库和通知用户。
一个数据库事务代码如下:
boolean autoCommitDefault = conn.getAutoCommit(); try { conn.setAutoCommit(false); /* 在此基于有事务控制的conn执行你的代码 */ conn.commit(); } catch (Throwable e) { try { conn.rollback(); } catch (Throwable ignore) {} throw e; } finally { try { conn.setAutoCommit(autoCommitDefault); } catch (Throwable ignore) {} }