https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5
**Java数据库连接**,(**Java Database Connectivity**,简称**JDBC**)是[Java语言](https://zh.wikipedia.org/wiki/Java%E8%AF%AD%E8%A8%80 "Java语言")中用来规范[客户端](https://zh.wikipedia.org/wiki/%E5%AE%A2%E6%88%B7%E7%AB%AF "客户端")程序如何来访问[数据库](https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E5%BA%93 "数据库")的[应用程序接口](https://zh.wikipedia.org/wiki/%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E6%8E%A5%E5%8F%A3 "应用程序接口"),提供了诸如查询和更新数据库中数据的方法。JDBC也是[Sun Microsystems](https://zh.wikipedia.org/wiki/Sun_Microsystems "Sun Microsystems")的[商标](https://zh.wikipedia.org/wiki/%E5%95%86%E6%A0%87 "商标")[\[1\]](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#cite_note-1)。JDBC是面向[关系型数据库](https://zh.wikipedia.org/wiki/%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93 "关系型数据库")的。
在[J2SE](https://zh.wikipedia.org/wiki/J2SE "J2SE")中,提供了一个称之为JDBC-ODBC桥(JDBC-ODBC Bridge[\[2\]](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#cite_note-2))的API。通过[ODBC](https://zh.wikipedia.org/wiki/ODBC "ODBC"),JDBC-ODBC桥[驱动程序](https://zh.wikipedia.org/wiki/%E9%A9%B1%E5%8A%A8%E7%A8%8B%E5%BA%8F "驱动程序")可以访问所有支持ODBC的关系型数据库。与JDBC API不同的是,这个驱动程序并不是由Java代码而是由[机器代码](https://zh.wikipedia.org/wiki/%E6%9C%BA%E5%99%A8%E8%AF%AD%E8%A8%80 "机器语言")(native code)编写,并且不是[开放源代码](https://zh.wikipedia.org/wiki/%E5%BC%80%E6%94%BE%E6%BA%90%E4%BB%A3%E7%A0%81 "开放源代码")的[\[3\]](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#cite_note-3)。
## 目录
* [1驱动程序类型](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#%E9%A9%B1%E5%8A%A8%E7%A8%8B%E5%BA%8F%E7%B1%BB%E5%9E%8B)
* [1.1类型1:JDBC-ODBC桥](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#%E7%B1%BB%E5%9E%8B1%EF%BC%9AJDBC-ODBC%E6%A1%A5)
* [1.2类型2:本地API驱动](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#%E7%B1%BB%E5%9E%8B2%EF%BC%9A%E6%9C%AC%E5%9C%B0API%E9%A9%B1%E5%8A%A8)
* [1.3类型3:网络协议驱动](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#%E7%B1%BB%E5%9E%8B3%EF%BC%9A%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE%E9%A9%B1%E5%8A%A8)
* [1.4类型4:本地协议驱动](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#%E7%B1%BB%E5%9E%8B4%EF%BC%9A%E6%9C%AC%E5%9C%B0%E5%8D%8F%E8%AE%AE%E9%A9%B1%E5%8A%A8)
* [2API概述](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#API%E6%A6%82%E8%BF%B0)
* [2.1数据类型的映射](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%98%A0%E5%B0%84)
* [3例子](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#%E4%BE%8B%E5%AD%90)
* [4参考文献](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE)
* [5外部链接](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#%E5%A4%96%E9%83%A8%E9%93%BE%E6%8E%A5)
* [6参见](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#%E5%8F%82%E8%A7%81)
## 驱动程序类型\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=1 "编辑章节:驱动程序类型")\]
JDBC驱动程序共分四种类型:
### 类型1:JDBC-ODBC桥\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=2 "编辑章节:类型1:JDBC-ODBC桥")\]
这种类型的驱动把所有JDBC的调用传递给ODBC,再让后者调用数据库本地驱动代码(也就是数据库厂商提供的数据库操作二进制代码库,例如[Oracle](https://zh.wikipedia.org/wiki/Oracle "Oracle")中的oci.dll)。
优点:
* 只要有对应的ODBC驱动(大部分数据库厂商都会提供),几乎可以访问所有的数据库。
缺点:
* 执行效率比较低,不适合大数据量访问的应用;
* 由于需要客户端预装对应的ODBC驱动,不适合Internet/Intranet应用。
### 类型2:本地API驱动\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=3 "编辑章节:类型2:本地API驱动")\]
这种类型的驱动通过客户端加载数据库厂商提供的本地代码库([C](https://zh.wikipedia.org/wiki/C%E8%AF%AD%E8%A8%80 "C语言")/[C++](https://zh.wikipedia.org/wiki/C%2B%2B "C++")等)来访问数据库,而在驱动程序中则包含了Java代码。
优点:
* 速度快于第一类驱动(但仍比不上第3、第4类驱动)。
缺点
* 由于需要客户端预装对应的数据库厂商代码库,仍不适合Internet/Intranet应用。
### 类型3:网络协议驱动\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=4 "编辑章节:类型3:网络协议驱动")\]
这种类型的驱动给客户端提供了一个网络API,客户端上的JDBC驱动程序使用[套接字](https://zh.wikipedia.org/wiki/%E5%A5%97%E6%8E%A5%E5%AD%97 "套接字")(Socket)来调用服务器上的中间件程序,后者在将其请求转化为所需的具体API调用。
优点:
* 不需要在客户端加载数据库厂商提供的代码库,单个驱动程序可以对多个数据库进行访问,可扩展性较好。
缺点:
* 在中间件层仍需对最终数据进行配置;
* 由于多出一个中间件层,速度不如第四类驱动程序。
### 类型4:本地协议驱动\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=5 "编辑章节:类型4:本地协议驱动")\]
这种类型的驱动使用Socket,直接在客户端和数据库间通信。
优点:
* 访问速度最快;
* 这是最直接、最纯粹的[Java](https://zh.wikipedia.org/wiki/Java "Java")实现。
缺点:
* 几乎只有数据库厂商自己才能提供这种类型的JDBC驱动。
* 需要针对不同的数据库使用不同的驱动程序。
## API概述\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=6 "编辑章节:API概述")\]
*参看[JavaSE](https://zh.wikipedia.org/w/index.php?title=JavaSE&action=edit&redlink=1 "JavaSE(页面不存在)")以及[java.sql API](https://web.archive.org/web/20050709074831/http://java.sun.com/j2se/1.4.2/docs/api/java/sql/package-summary.html)*
JDBC API主要位于JDK中的java.sql包中(之后扩展的内容位于javax.sql包中),主要包括(斜体代表接口,需驱动程序提供者来具体实现):
* DriverManager:负责加载各种不同驱动程序(Driver),并根据不同的请求,向调用者返回相应的数据库连接(Connection)。
* *Driver*:驱动程序,会将自身加载到DriverManager中去,并处理相应的请求并返回相应的数据库连接(Connection)。
* *Connection*:数据库连接,负责进行与数据库间的通讯,[SQL](https://zh.wikipedia.org/wiki/SQL "SQL")执行以及事务处理都是在某个特定Connection环境中进行的。可以产生用以执行SQL的Statement。
* *Statement*:用以执行SQL查询和更新(针对静态SQL语句和单次执行)。
* *PreparedStatement*:用以执行包含动态参数的SQL查询和更新(在服务器端编译,允许重复执行以提高效率)。
* *CallableStatement*:用以调用数据库中的[存储过程](https://zh.wikipedia.org/wiki/%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B "存储过程")。
* SQLException:代表在数据库连接的创建和关闭和SQL语句的执行过程中发生了例外情况(即错误)。
### 数据类型的映射\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=7 "编辑章节:数据类型的映射")\]
从SQL到Java数据类型映射的JDBC规范SQL类型Java类型CHARjava.lang.StringVARCHARjava.lang.StringLONGVARCHARjava.lang.StringNUMERICjava.math.BigDecimalDECIMALjava.math.BigDecimalBITbooleanTINYINTbyteSMALLINTshortINTEGERintBIGINTlongREALfloatFLOATdoubleDOUBLEdoubleBINARYbyte[]VARBINARYbyte[]LONGVARBINARYbyte[]DATEjava.sql.DateTIMEjava.sql.TimeTIMESTAMPjava.sql.TimestampBLOBjava.sql.BlobCLOBjava.sql.ClobArrayjava.sql.ArrayREFjava.sql.RefStructjava.sql.Struct
注:这种类型匹配不是强制性标准,特定的JDBC厂商可能会改变这种类型匹配。例如Oracle中的DATE类型是包含时分秒,而java.sql.Date仅仅支持年月日。
## 例子\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=8 "编辑章节:例子")\]
利用Class.forName()方法来加载JDBC驱动程序(*Driver*)至DriverManager:
~~~
Class.forName( "com.somejdbcvendor.TheirJdbcDriver" );
~~~
然后,从DriverManager中,通过JDBC[URL](https://zh.wikipedia.org/wiki/URL "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[程序员](https://zh.wikipedia.org/wiki/%E7%A8%8B%E5%BA%8F%E5%91%98 "程序员")们更倾向于使用*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](https://zh.wikipedia.org/w/index.php?title=SQLException&action=edit&redlink=1 "SQLException(页面不存在)")。一般来说,此类异常很少能够恢复,唯一能做的就是尽可能详细的打印异常日记。推荐的做法是将SQLException翻译成应用程序领域相关的异常(非强制处理异常)并最终回滚数据库和通知用户。
一个[数据库事务](https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BA%8B%E5%8A%A1 "数据库事务")代码如下:
~~~
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) {}
}
~~~
## 参考文献\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=9 "编辑章节:参考文献")\]
1. [↑](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#cite_ref-1 "跳转")[\[1\]](http://java.sun.com/j2se/1.5.0/docs/guide/jdbc/getstart/intro.html#1018466)
2. [↑](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#cite_ref-2 "跳转")[存档副本](https://web.archive.org/web/20050714002258/http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/bridge.doc.html).\[2005-07-11\]. ([原始内容](http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/bridge.doc.html)存档于2005-07-14).
3. [↑](https://zh.wikipedia.org/wiki/Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5#cite_ref-3 "跳转")[\[2\]](http://java.sun.com/products/jdbc/jdbc-3_0-fr-spec-license.html)
## 外部链接\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=10 "编辑章节:外部链接")\]
* [Sun提供的JDBC驱动程序及其供应商列表](https://archive.is/20030803212350/http://servlet.java.sun.com/products/jdbc/drivers)
* [Sun提供的教程](https://web.archive.org/web/20041209205155/http://java.sun.com/docs/books/tutorial/post1.0/whatsnew/jdbc.html)
* [Sun Java 2 1.4.2 API](http://java.sun.com/j2se/1.4.2/docs/api/)
* [一个订单系统的原形](http://java.sun.com/developer/technicalArticles/Database/dukesbakery/)
* [DBAccessor: JDBC数据库访问封装类](http://java.sun.com/developer/technicalArticles/Database/dbaccessor/)
* [开源的JDBC驱动程序列表](http://java-source.net/open-source/database-engines)
* [http://blog.csdn.net/cho3en1/article/details/52695808](http://blog.csdn.net/cho3en1/article/details/52695808)
## 参见\[[编辑](https://zh.wikipedia.org/w/index.php?title=Java%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5&action=edit§ion=11 "编辑章节:参见")\]
* [![icon](https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Crystal_Clear_device_cdrom_unmount.png/28px-Crystal_Clear_device_cdrom_unmount.png)](https://zh.wikipedia.org/wiki/File:Crystal_Clear_device_cdrom_unmount.png)[软件主题](https://zh.wikipedia.org/wiki/Portal:%E8%BD%AF%E4%BB%B6 "Portal:软件")
* [![icon](https://upload.wikimedia.org/wikipedia/commons/thumb/c/cc/8bit-dynamiclist_%28reversed%29.gif/28px-8bit-dynamiclist_%28reversed%29.gif)](https://zh.wikipedia.org/wiki/File:8bit-dynamiclist_(reversed).gif)[计算机程序设计主题](https://zh.wikipedia.org/wiki/Portal:%E9%9B%BB%E8%85%A6%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88 "Portal:计算机程序设计")
* [数据库](https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E5%BA%93 "数据库")
* [Java](https://zh.wikipedia.org/wiki/Java "Java")
* [J2SE](https://zh.wikipedia.org/wiki/J2SE "J2SE")
* [J2EE](https://zh.wikipedia.org/wiki/J2EE "J2EE")
* [ODBC](https://zh.wikipedia.org/wiki/ODBC "ODBC")
* [ADO](https://zh.wikipedia.org/wiki/ADO "ADO")
* [ADO.NET](https://zh.wikipedia.org/wiki/ADO.NET "ADO.NET")
- 数据库
- CAP定理
- 关系模型
- 关系数据库
- NoSQL
- ODBC
- JDBC
- ODBC、JDBC和四种驱动类型
- mysql
- 安装与配置
- CentOS 7 安装 MySQL
- 优化
- 比较全面的MySQL优化参考
- 1、硬件层相关优化
- 1.1、CPU相关
- 1.2、磁盘I/O相关
- 2、系统层相关优化
- 2.1、文件系统层优化
- 2.2、其他内核参数优化
- 3、MySQL层相关优化
- 3.1、关于版本选择
- 3.2、关于最重要的参数选项调整建议
- 3.3、关于Schema设计规范及SQL使用建议
- 3.4、其他建议
- 后记
- Mysql设计与优化专题
- ER图,数据建模与数据字典
- 数据中设计中的范式与反范式
- 字段类型与合理的选择字段类型
- 表的垂直拆分和水平拆分
- 详解慢查询
- mysql的最佳索引攻略
- 高手详解SQL性能优化十条经验
- 优化SQL查询:如何写出高性能SQL语句
- MySQL索引原理及慢查询优化
- 数据库SQL优化大总结之 百万级数据库优化方案
- 数据库性能优化之SQL语句优化1
- 【重磅干货】看了此文,Oracle SQL优化文章不必再看!
- MySQL 对于千万级的大表要怎么优化?
- MySQL 数据库设计总结
- MYSQL性能优化的最佳20+条经验
- 数据操作
- 数据语句操作类型
- DCL
- 修改Mysql数据库名的5种方法
- DML
- 连接
- 连接2
- DDL
- 数据类型
- 字符集
- 表引擎
- 索引
- MySQL理解索引、添加索引的原则
- mysql建索引的几大原则
- 浅谈mysql的索引设计原则以及常见索引的区别
- 常用工具简介
- QA
- MySQL主机127.0.0.1与localhost区别总结
- 视图(view)
- 触发器
- 自定义函数和存储过程的使用
- 事务(transaction)
- 范式与反范式
- 常用函数
- MySQL 数据类型 详解
- Mysql数据库常用分库和分表方式
- 隔离级别
- 五分钟搞清楚MySQL事务隔离级别
- mysql隔离级别及事务传播
- 事务隔离级别和脏读的快速入门
- 数据库引擎中的隔离级别
- 事务隔离级别
- Innodb中的事务隔离级别和锁的关系
- MySQL 四种事务隔离级的说明
- Innodb锁机制:Next-Key Lock 浅谈
- SQL函数和存储过程的区别
- mongo
- MongoDB设置访问权限、设置用户
- redis
- ORM
- mybatis
- $ vs #
- mybatis深入理解(一)之 # 与 $ 区别以及 sql 预编译
- 电商设计
- B2C电子商务系统研发——概述篇
- B2C电子商务系统研发——商品数据模型设计
- B2C电子商务系统研发——商品模块E-R图建模
- B2C电子商务系统研发——商品SKU分析和设计(一)
- B2C电子商务系统研发——商品SKU分析和设计(二)
- 数据库命名规范--通用