什么是JDBC?
Java語(yǔ)言訪問數(shù)據(jù)庫(kù)的一種規(guī)范,是一套API
JDBC (Java Database Connectivity) API,即Java數(shù)據(jù)庫(kù)編程接口,是一組標(biāo)準(zhǔn)的Java語(yǔ)言中的接口和類,使用這些接口和類,Java客戶端程序可以訪問各種不同類型的數(shù)據(jù)庫(kù)。比如建立數(shù)據(jù)庫(kù)連接、執(zhí)行SQL語(yǔ)句進(jìn)行數(shù)據(jù)的存取操作。
JDBC規(guī)范采用接口和實(shí)現(xiàn)分離的思想設(shè)計(jì)了Java數(shù)據(jù)庫(kù)編程的框架。接口包含在java.sql及javax.sql包中,其中java.sql屬于JavaSE,javax.sql屬于JavaEE。這些接口的實(shí)現(xiàn)類叫做數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序,由數(shù)據(jù)庫(kù)的廠商或其它的廠商或個(gè)人提供。
為了使客戶端程序獨(dú)立于特定的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序,JDBC規(guī)范建議開發(fā)者使用基于接口的編程方式,即盡量使應(yīng)用僅依賴java.sql及javax.sql中的接口和類。
JDBC驅(qū)動(dòng)程序:
什么是JDBC驅(qū)動(dòng)程序?
這些是各個(gè)數(shù)據(jù)庫(kù)廠家根據(jù)JDBC的規(guī)范制作的JDBC實(shí)現(xiàn)類
JDBC驅(qū)動(dòng)程序的四種類型:
1. 第一種類型的驅(qū)動(dòng)程序的實(shí)現(xiàn)是通過將JDBC的調(diào)用全部委托給其它編程接口來實(shí)現(xiàn)的,比如ODBC。這種類型的驅(qū)動(dòng)程序需要安裝本地代碼庫(kù),即依賴于本地的程序,所以便攜性較差。比如JDBC-ODBC橋驅(qū)動(dòng)程序
2. 第二種類型的驅(qū)動(dòng)程序的實(shí)現(xiàn)是部分基于Java語(yǔ)言的。即該驅(qū)動(dòng)程序一部分是用Java語(yǔ)言編寫,其它部分委托本地的數(shù)據(jù)庫(kù)的客戶端代碼來實(shí)現(xiàn)。同類型1的驅(qū)動(dòng)一樣,該類型的驅(qū)動(dòng)程序也依賴本地的程序,所以便攜性較差
3. 第三種類型的驅(qū)動(dòng)程序的實(shí)現(xiàn)是全部基于JAVA語(yǔ)言的。該類型的驅(qū)動(dòng)程序通常由某個(gè)中間件服務(wù)器提供,這樣客戶端程序可以使用數(shù)據(jù)庫(kù)無關(guān)的協(xié)議和中間件服務(wù)器進(jìn)行通信,中間件服務(wù)器再將客戶端的JDBC調(diào)用轉(zhuǎn)發(fā)給數(shù)據(jù)庫(kù)進(jìn)行處理
4. 第四種類型的驅(qū)動(dòng)程序的實(shí)現(xiàn)是全部基于JAVA語(yǔ)言的。該類型的驅(qū)動(dòng)程序中包含了特定數(shù)據(jù)庫(kù)的訪問協(xié)議,使得客戶端可以直接和數(shù)據(jù)庫(kù)進(jìn)行通信
JDBC類結(jié)構(gòu):
DriverManager
Driver Driver
Connection Connection
Statement Statement
Resultset Resultset
DriverManager:這個(gè)是一個(gè)實(shí)現(xiàn)類,它是一個(gè)工廠類,用來生產(chǎn)Driver對(duì)象的
這個(gè)類的結(jié)構(gòu)設(shè)計(jì)模式為工廠方法
Driver:這是驅(qū)動(dòng)程序?qū)ο蟮慕涌?/span>,它指向一個(gè)實(shí)實(shí)在在的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序?qū)ο?/span>,那么這個(gè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序?qū)ο笫菑哪睦飦淼哪?/span>?
DriverManager工廠中有個(gè)方法:getDriver(String URL),通過這個(gè)方法可以得到驅(qū)動(dòng)程序?qū)ο?/span>,這個(gè)方法是在各個(gè)數(shù)據(jù)庫(kù)廠商按JDBC規(guī)范設(shè)計(jì)的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序包里的類中靜態(tài)實(shí)現(xiàn)的,也就是在靜態(tài)塊中
Connection:這個(gè)接口可以制向一個(gè)數(shù)據(jù)庫(kù)連接對(duì)象,那么如何得到這個(gè)連接對(duì)象呢?
是通過DriverManager工廠中的getConnection(String URL)方法得到的
Statement:用于執(zhí)行靜態(tài)的SQL語(yǔ)句的接口,通過Connection中的createStatement方法得到的
Resultset:用于指向結(jié)果集對(duì)象的接口,結(jié)果集對(duì)象是通過Statement中的execute等方法得到的
JAVA使用JDBC訪問數(shù)據(jù)庫(kù)的步驟:
1. 得到數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序
2. 創(chuàng)建數(shù)據(jù)庫(kù)連接
3. 執(zhí)行SQL語(yǔ)句
4. 得到結(jié)果集
5. 對(duì)結(jié)果集做相應(yīng)的處理(增,刪,改,查)
6. 關(guān)閉資源:這里釋放的是DB中的資源
設(shè)置classpath:
1. 在java文件中起的包名一定要是工程基目錄下的子目錄,classpath:基目錄
2. .jar包,需要將這個(gè).jar包的路徑包括這個(gè)文件的全名添加到classpath中來
Oracle連接字符串的書寫格式:
“oracle:jdbc:thin:@ip:1521: 數(shù)據(jù)庫(kù)名”,”數(shù)據(jù)庫(kù)用戶名”,”數(shù)據(jù)庫(kù)密碼”
簡(jiǎn)單的例子:
package moudule1.first;
import java.sql.*;
public class FirstJdbc
{
public static void main(String[] args)
{
String sql="select * from yuchen_user";
Connection con=null;
Statement st=null;
ResultSet rs=null;
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:name", "scott","tiger");
st=con.createStatement();
rs=st.executeQuery(sql);
while(rs.next())
{
System.out.println(rs.getInt("id"));
System.out.println(rs.getString("name"));
}
}catch(Exception e)
{
e.printStackTrace();
}finally
{
try
{
con.close();
}catch(Exception e)
{}
try
{
st.close();
}catch(Exception e)
{
}
try
{
rs.close();
}catch(Exception e)
{
}
}
}
}
常用數(shù)據(jù)庫(kù)的驅(qū)動(dòng)程序及JDBC URL:
Oracle數(shù)據(jù)庫(kù):
驅(qū)動(dòng)程序包名:ojdbc14.jar
驅(qū)動(dòng)類的名字:oracle.jdbc.driver.OracleDriver
JDBC URL:jdbc:oracle:thin:@dbip:port:databasename
說明:驅(qū)動(dòng)程序包名有可能會(huì)變
JDBC URL中黑色字體部分必須原封不動(dòng)的保留,為該驅(qū)動(dòng)識(shí)別的URL格式。紅色字體部分需要根據(jù)數(shù)據(jù)庫(kù)的安裝情況填寫。其中各個(gè)部分含義如下:
dbip –為數(shù)據(jù)庫(kù)服務(wù)器的IP地址,如果是本地可寫:localhost或127.0.0.1。
port –為數(shù)據(jù)庫(kù)的監(jiān)聽端口,需要看安裝時(shí)的配置,缺省為1521。
databasename –為數(shù)據(jù)庫(kù)的SID,通常為全局?jǐn)?shù)據(jù)庫(kù)的名字。
舉例如果要訪問本地的數(shù)據(jù)庫(kù)allandb,端口1521,那么URL寫法如下:
jdbc:oracle:thin:@localhost:1521:allandb 下載地址如下:
http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/index.html
SQL Server數(shù)據(jù)庫(kù)
驅(qū)動(dòng)程序包名:msbase.jar mssqlserver.jar msutil.jar
驅(qū)動(dòng)類的名字:com.microsoft.jdbc.sqlserver.SQLServerDriver
JDBC URL:jdbc:microsoft:sqlserver://dbip:port;DatabaseName=databasename
說明:驅(qū)動(dòng)程序包名有可能會(huì)變
JDBC URL中黑色字體部分必須原封不動(dòng)的保留,為該驅(qū)動(dòng)識(shí)別的URL格式。紅色字體部需要根據(jù)數(shù)據(jù)庫(kù)的安裝情況填寫。其中各個(gè)部分含義如下:
dbip –為數(shù)據(jù)庫(kù)服務(wù)器的IP地址,如果是本地可寫:localhost或127.0.0.1。
port –為數(shù)據(jù)庫(kù)的監(jiān)聽端口,需要看安裝時(shí)的配置,缺省為1433。
databasename –數(shù)據(jù)庫(kù)的名字。
舉例如果要訪問本地的數(shù)據(jù)庫(kù)allandb,端口1433,那么URL寫法如下:
jdbc: microsoft: sqlserver:@localhost:1433; DatabaseName =allandb
下載地址:http://www.microsoft.com/downloads/details.aspx
MySQL數(shù)據(jù)庫(kù)
驅(qū)動(dòng)程序包名:mysql-connector-java-3.1.11-bin.jar
驅(qū)動(dòng)類的名字:com.mysql.jdbc.Driver
JDBC URL:jdbc:mysql://dbip:port/databasename
說明:驅(qū)動(dòng)程序包名有可能會(huì)變
JDBC URL中黑色字體部分必須原封不動(dòng)的保留,為該驅(qū)動(dòng)識(shí)別的URL格式。紅色字體部需要根據(jù)數(shù)據(jù)庫(kù)的安裝情況填寫。其中各個(gè)部分含義如下:
dbip –為數(shù)據(jù)庫(kù)服務(wù)器的IP地址,如果是本地可寫:localhost或127.0.0.1。
port –為數(shù)據(jù)庫(kù)的監(jiān)聽端口,需要看安裝時(shí)的配置,缺省為3306。
databasename –數(shù)據(jù)庫(kù)的名字。
舉例如果要訪問本地的數(shù)據(jù)庫(kù)allandb,端口1433,那么URL寫法如下:
jdbc:mysql://localhost:3306/allandb
下載地址:http://dev.mysql.com/downloads/connector/j/
Access數(shù)據(jù)庫(kù)
驅(qū)動(dòng)程序包名:該驅(qū)動(dòng)程序包含在JavaSE中,不需要額外安裝。
驅(qū)動(dòng)類的名字:sun.jdbc.odbc.JdbcOdbcDriver
JDBC URL:jdbc:odbc:datasourcename
說明:該驅(qū)動(dòng)只能工作在Windows系統(tǒng)中,首先需要在操作系統(tǒng)中建立一個(gè)可以訪問Access數(shù)據(jù)庫(kù)的本地?cái)?shù)據(jù)源(ODBC),如果名字為allandb,那么URL寫法如下:
jdbc:odbc:allandb
PreparedStatement接口:
預(yù)編譯的sql語(yǔ)句對(duì)象
作用: 解決了書寫sql語(yǔ)句時(shí)一些特殊的字符與sql保留字符沖突的問題,非常方便
/**
*知識(shí)點(diǎn):
*PreparedStatement接口及方法的使用
*程序目標(biāo):
*java文件:
*PreparedInsert.java:連接數(shù)據(jù)庫(kù),插入一條數(shù)據(jù)
*JdbcUtil.java:實(shí)現(xiàn)一個(gè)工具類,功能:1.連接數(shù)據(jù)庫(kù) 2.關(guān)閉資源
*/
package moudule1.preparedstatement;
import java.sql.*;
import moudule1.com.*;
public class PreparedInsert
{
public static void main(String[] args)
{
String sql="insert into yuchen_user (id,name) values (?,?)";
System.out.println(sql);
Connection con=null;
PreparedStatement ps=null;
try{
con=JdbcUtil.getConnection();
ps=con.prepareStatement(sql);
ps.setInt(1,2);
ps.setString(2,"zhangsan");
ps.executeUpdate();
ps.setInt(1,3);
ps.setString(2,"lisi");
ps.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,ps);
}
}
}
package moudule1.com;
import java.sql.*;
public class JdbcUtil{
public static Connection getConnection() throws Exception{
Class.forName("oracle.jdbc.driver.OracleDriver");
return DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:name", "scott","tiger");
}
public static void close(Connection con,Statement st){
close(con);
close(st);
}
public static void close(Connection con,Statement st,ResultSet rs){
close(con,st);
close(rs);
}
public static void close(Connection con){
try{
con.close();
}catch(Exception e){
}
}
public static void close(Statement st){
try{
st.close();
}catch(Exception e){
}
}
public static void close(ResultSet rs){
try{
rs.close();
}catch(Exception e){
}
}
}
數(shù)據(jù)庫(kù)的增刪改查的例子:
/**
*知識(shí)點(diǎn):
*JDBC+SQL+ORACLE
*程序目標(biāo):
*UserDao.java:實(shí)現(xiàn)了數(shù)據(jù)庫(kù)的增刪改查
*JdbcUtil.java:工具類,有連庫(kù)和關(guān)閉資源的方法
*/
package moudule1.idus;
import java.sql.*;
import moudule1.com.*;
public class UserDao{
private String sql;
private Connection con;
private Statement st;
private ResultSet rs;
public UserDao(){
sql=null;
con=null;
st=null;
rs=null;
}
public void insert(){
sql="insert into yuchen_user (id,name) values(";
sql+="4,‘zhouwu‘)";
System.out.println(sql);
try{
con=JdbcUtil.getConnection();
st=con.createStatement();
st.executeUpdate(sql);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,st);
}
}
public void delete(){
sql="delete from yuchen_user where id=2";
System.out.println(sql);
try{
con=JdbcUtil.getConnection();
st=con.createStatement();
st.executeUpdate(sql);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,st);
}
}
public void update(){
sql="update yuchen_user set name=‘liumang‘ where id=1";
System.out.println(sql);
try{
con=JdbcUtil.getConnection();
st=con.createStatement();
st.executeUpdate(sql);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,st);
}
}
public void select(){
sql="select * from yuchen_user";
System.out.println(sql);
try{
con=JdbcUtil.getConnection();
st=con.createStatement();
rs=st.executeQuery(sql);
while(rs.next()){
System.out.println(rs.getInt(1));
System.out.println(rs.getString(2));
}
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,st,rs);
}
}
public static void main(String[] args){
UserDao ud=new UserDao();
ud.select();
ud.insert();
ud.select();
ud.update();
ud.select();
ud.delete();
ud.select();
}
}
一些常用的方法:
/**
*知識(shí)點(diǎn):
*execute方法,getResultSet(),getUpdateCount()
*程序目標(biāo):
*JdbcUtil.java:工具類,連接數(shù)據(jù)庫(kù),關(guān)閉資源
*sqlExecutor.java:命令行參數(shù)輸入sql語(yǔ)句,并執(zhí)行該語(yǔ)句
*/
package moudule1.fangfa;
import java.sql.*;
import moudule1.com.*;
public class sqlExecutor{
public static void main(String[] args){
Connection con=null;
Statement st=null;
try{
con=JdbcUtil.getConnection();
st=con.createStatement();
boolean str=st.execute(args[0]);
if(str){
ResultSet rs=st.getResultSet();
while(rs.next()){
System.out.println(rs.getInt("id")+":"+rs.getString("name"));
}
rs.close();
}else{
int row=st.getUpdateCount();
System.out.println(row);
}
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,st);
}
}
}
2. 補(bǔ)充
加載及注冊(cè)JDBC驅(qū)動(dòng)程序
Class.forName("com.mysql.jdbc.Driver");
Class.forName("com.mysql.jdbc.Driver").newInstance();
JDBC URL 定義驅(qū)動(dòng)程序與數(shù)據(jù)源之間的連接
標(biāo)準(zhǔn)語(yǔ)法:
<protocol(主要通訊協(xié)議)>:<subprotocol(次要通訊協(xié)議,即驅(qū)動(dòng)程序名稱)>:<data source identifier(數(shù)據(jù)源)>
MySQL的JDBC URL格式:
jdbc:mysql//[hostname][:port]/[dbname][?param1=value1][¶m2=value2]….
示例:jdbc:mysql://localhost:3306/sample_db?user=root&password=your_password
常見參數(shù):
user 用戶名
password 密碼
autoReconnect 聯(lián)機(jī)失敗,是否重新聯(lián)機(jī)(true/false)
maxReconnect 嘗試重新聯(lián)機(jī)次數(shù)
initialTimeout 嘗試重新聯(lián)機(jī)間隔
maxRows 傳回最大行數(shù)
useUnicode 是否使用Unicode字體編碼(true/false)
characterEncoding 何種編碼(GB2312/UTF-8/…)
relaxAutocommit 是否自動(dòng)提交(true/false)
capitalizeTypeNames 數(shù)據(jù)定義的名稱以大寫表示
建立連接對(duì)象
String url="jdbc:mysql://localhost:3306/sample_db?user=root&password=your_password";
Connection con = DriverManager.getConnection(url);
建立SQL陳述式對(duì)象(Statement Object)
Statement stmt = con.createStatement();
執(zhí)行SQL語(yǔ)句
executeQuery()
String query = "select * from test";
ResultSet rs=stmt.executeQuery(query);
結(jié)果集ResultSet
while(rs.next())
{rs.getString(1);rs.getInt(2);}
executeUpdate()
String upd="insert into test (id,name) values(1001,xuzhaori)";
int con=stmt.executeUpdate(upd);
execute()
示例:
try{
}
catch(SQLException sqle)
{
}
finally
{
}
Java類型和SQL類型 技術(shù)手冊(cè)P421
PreparedStatement(預(yù)編語(yǔ)句)
PreparedStatement stmt = conn.prepareStatement("insert into test(id,name)values(?,?)");
stmt.setInt(1,id);
stmt.setString(2,name);
注:一旦設(shè)定語(yǔ)句的參數(shù)值后,就可以多次執(zhí)行改語(yǔ)句,直到調(diào)用clearParameters()方法將他清除為止
CallableStatement(預(yù)儲(chǔ)程序)技術(shù)手冊(cè)P430
JDBC2.0使用
ResultSet對(duì)象中的光標(biāo)上下自由移動(dòng)
Statement stmt = con.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs=stmt.executeQuery("select * from test");
public Statement createStatement(int resultSetType,int resultSetConcuttency) throws SQLException
resultSetType
TYPE_FORWARD_ONLY 只能使用next()方法。
TYPE_SCROLL_SENSITIVE 可以上下移動(dòng),可以取得改變后的值。
TYPE_SCROLL_INSENSITIVE 可以上下移動(dòng)。
resultSetConcuttency
CONCUR_READ_ONLY 只讀
CONCUR_UPDATABLE ResultSet對(duì)象可以執(zhí)行數(shù)據(jù)庫(kù)的新增、修改、和移除
直接使用ResultSet對(duì)象執(zhí)行更新數(shù)據(jù)
新增數(shù)據(jù)
Statement stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_PUDATABLE);
ResultSet uprs=stmt.executeQuery("select * from test");
uprs.moveToInsertRow();
uprs.updateInt(1,1001);
uprs.updateString(2,"許召日");
uprs.insertRow;
更新數(shù)據(jù)
Statement stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_PUDATABLE);
ResultSet uprs=stmt.executeQuery("select * from test");
uprs.last();
uprs.updateString("name","xuzhaori");
uprs.updateRow;
刪除數(shù)據(jù)
Statement stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_PUDATABLE);
ResultSet uprs=stmt.executeQuery("select * from test");
uprs.absolute(4);
uprs.deleteRow();
批處理
con.setAutoCommit(false); 關(guān)閉自動(dòng)認(rèn)可模式
Statement stmt=con.createStatement();
int[] rows;
stmt.addBatch("insert into test values(1001,xuzhaori)");
stmt.addBatch("insert into test values(1002,xuyalin)");
rows=stmt.executeBatch();
con.commit(); 沒有任何錯(cuò)誤,執(zhí)行批處理stmt.executeBatch();
JNDI-數(shù)據(jù)源(Data Source)與連接池(Connection Pool)
Tomcat的JDBC數(shù)據(jù)源設(shè)置 技術(shù)手冊(cè)P439
連接池工具-Proxool Var 0.8.3 技術(shù)手冊(cè)P446
設(shè)置web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--<?xml version="1.0" encoding="GB2312"?>-->
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
….
<servlet>
<servlet-name>ServletConfigurator</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
<init-param>
<param-name>propertyFile</param-name>
<param-value>WEB-INF/classes/Proxool.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
后端統(tǒng)計(jì)端口添加下列
<servlet>
<servlet-name>Admin</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Admin</servlet-name>
<url-pattern>/Admin</url-pattern>
</servlet-mapping>
….
</web-app>
配置Proxool.properties
jdbc-0.proxool.alias=JSPBook
jdbc-0.proxool.driver-class=com.mysql.jdbc.Driver
jdbc-0.proxool.driver-url=jdbc:mysql://localhost:3306/sample_db?user=root&password=browser&useUnicode=true&characterEncoding=UTF-8
jdbc-0.proxool.maximum-connection-count=10
jdbc-0.proxool.prototype-count=4
jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE
jdbc-0.proxool.verbose=true
jdbc-0.proxool.statistics=10s,1m,1d 后端統(tǒng)計(jì)接口添加此行
jdbc-0.proxool.statistics-log-level=DEBUG
使用Proxool連接池
Connection con = DriverManager.getConnection("proxool.JSPBook");
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
String query = "SELECT * FROM employee";
ResultSet rs = stmt.executeQuery(query);
聯(lián)系客服