2014-11-25 15:39 853人閱讀 評論(0) 收藏 舉報javascript
分類:html
Java/Jsp/javascript(27) java
版權聲明:本文爲博主原創文章,未經博主容許不得轉載。mysql
from:http://www.cnblogs.com/lee/archive/2007/08/25/869656.html;http://blog.csdn.NET/lovesomnus/article/details/22822317web
什麼是JDBC?sql
JDBC (Java Database Connectivity) API,即Java數據庫編程接口,是一組標準的Java語言中的接口和類,使用這些接口和類,Java客戶端程序能夠訪問各類不一樣類型的數據庫。好比創建數據庫鏈接、執行SQL語句進行數據的存取操做。編程
JDBC規範採用接口和實現分離的思想設計了Java數據庫編程的框架。接口包含在java.sql及javax.sql包中,其中java.sql屬於JavaSE,javax.sql屬於JavaEE。這些接口的實現類叫作數據庫驅動程序,由數據庫的廠商或其它的廠商或我的提供。後端
爲了使客戶端程序獨立於特定的數據庫驅動程序,JDBC規範建議開發者使用基於接口的編程方式,即儘可能使應用僅依賴java.sql及javax.sql中的接口和類。設計模式
JDBC驅動程序:
什麼是JDBC驅動程序?
這些是各個數據庫廠家根據JDBC的規範製做的JDBC實現類
JDBC驅動程序的四種類型:
1. 第一種類型的驅動程序的實現是經過將JDBC的調用所有委託給其它編程接口來實現的,好比ODBC。這種類型的驅動程序須要安裝本地代碼庫,即依賴於本地的程序,因此便攜性較差。好比JDBC-ODBC橋驅動程序
2. 第二種類型的驅動程序的實現是部分基於Java語言的。即該驅動程序一部分是用Java語言編寫,其它部分委託本地的數據庫的客戶端代碼來實現。同類型1的驅動同樣,該類型的驅動程序也依賴本地的程序,因此便攜性較差
3. 第三種類型的驅動程序的實現是所有基於JAVA語言的。該類型的驅動程序一般由某個中間件服務器提供,這樣客戶端程序可使用數據庫無關的協議和中間件服務器進行通訊,中間件服務器再將客戶端的JDBC調用轉發給數據庫進行處理
4. 第四種類型的驅動程序的實現是所有基於JAVA語言的。該類型的驅動程序中包含了特定數據庫的訪問協議,使得客戶端能夠直接和數據庫進行通訊
JDBC類結構:
DriverManager
Driver Driver
Connection Connection
Statement Statement
Resultset Resultset
DriverManager:這個是一個實現類,它是一個工廠類,用來生產Driver對象的
這個類的結構設計模式爲工廠方法
Driver:這是驅動程序對象的接口,它指向一個實實在在的數據庫驅動程序對象,那麼這個數據庫驅動程序對象是從哪裏來的呢?
DriverManager工廠中有個方法:getDriver(String URL),經過這個方法能夠獲得驅動程序對象,這個方法是在各個數據庫廠商按JDBC規範設計的數據庫驅動程序包裏的類中靜態實現的,也就是在靜態塊中
Connection:這個接口能夠制向一個數據庫鏈接對象,那麼如何獲得這個鏈接對象呢?
是經過DriverManager工廠中的getConnection(String URL)方法獲得的
Statement:用於執行靜態的SQL語句的接口,經過Connection中的createStatement方法獲得的
Resultset:用於指向結果集對象的接口,結果集對象是經過Statement中的execute等方法獲得的
JAVA使用JDBC訪問數據庫的步驟:
1. 獲得數據庫驅動程序
2. 建立數據庫鏈接
3. 執行SQL語句
4. 獲得結果集
5. 對結果集作相應的處理(增,刪,改,查)
6. 關閉資源:這裏釋放的是DB中的資源
設置classpath:
1. 在java文件中起的包名必定要是工程基目錄下的子目錄,classpath:基目錄
2. .jar包,須要將這個.jar包的路徑包括這個文件的全名添加到classpath中來
Oracle鏈接字符串的書寫格式:
「oracle:jdbc:thin:@ip:1521: 數據庫名」,」數據庫用戶名」,」數據庫密碼」
簡單的例子:
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)
{
}
}
}
}
經常使用數據庫的驅動程序及JDBC URL:
Oracle數據庫:
驅動程序包名:ojdbc14.jar
驅動類的名字:oracle.jdbc.driver.OracleDriver
JDBC URL:jdbc:oracle:thin:@dbip:port:databasename
說明:驅動程序包名有可能會變
JDBC URL中黑色字體部分必須原封不動的保留,爲該驅動識別的URL格式。紅色字體部分須要根據數據庫的安裝狀況填寫。其中各個部分含義以下:
dbip –爲數據庫服務器的IP地址,若是是本地可寫:localhost或127.0.0.1。
port –爲數據庫的監聽端口,須要看安裝時的配置,缺省爲1521。
databasename –爲數據庫的SID,一般爲全局數據庫的名字。
舉例若是要訪問本地的數據庫allandb,端口1521,那麼URL寫法以下:
jdbc:oracle:thin:@localhost:1521:allandb 下載地址以下:
http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/index.html
SQL Server數據庫
驅動程序包名:msbase.jar mssqlserver.jar msutil.jar
驅動類的名字:com.microsoft.jdbc.sqlserver.SQLServerDriver
JDBC URL:jdbc:microsoft:sqlserver://dbip:port;DatabaseName=databasename
說明:驅動程序包名有可能會變
JDBC URL中黑色字體部分必須原封不動的保留,爲該驅動識別的URL格式。紅色字體部須要根據數據庫的安裝狀況填寫。其中各個部分含義以下:
dbip –爲數據庫服務器的IP地址,若是是本地可寫:localhost或127.0.0.1。
port –爲數據庫的監聽端口,須要看安裝時的配置,缺省爲1433。
databasename –數據庫的名字。
舉例若是要訪問本地的數據庫allandb,端口1433,那麼URL寫法以下:
jdbc: microsoft: sqlserver:@localhost:1433; DatabaseName =allandb
下載地址:http://www.microsoft.com/downloads/details.aspx
MySQL數據庫
驅動程序包名:mysql-connector-java-3.1.11-bin.jar
驅動類的名字:com.mysql.jdbc.Driver
JDBC URL:jdbc:mysql://dbip:port/databasename
說明:驅動程序包名有可能會變
JDBC URL中黑色字體部分必須原封不動的保留,爲該驅動識別的URL格式。紅色字體部須要根據數據庫的安裝狀況填寫。其中各個部分含義以下:
dbip –爲數據庫服務器的IP地址,若是是本地可寫:localhost或127.0.0.1。
port –爲數據庫的監聽端口,須要看安裝時的配置,缺省爲3306。
databasename –數據庫的名字。
舉例若是要訪問本地的數據庫allandb,端口1433,那麼URL寫法以下:
jdbc:mysql://localhost:3306/allandb
下載地址:http://dev.mysql.com/downloads/connector/j/
Access數據庫
驅動程序包名:該驅動程序包含在JavaSE中,不須要額外安裝。
驅動類的名字:sun.jdbc.odbc.JdbcOdbcDriver
JDBC URL:jdbc:odbc:datasourcename
說明:該驅動只能工做在Windows系統中,首先須要在操做系統中創建一個能夠訪問Access數據庫的本地數據源(ODBC),若是名字爲allandb,那麼URL寫法以下:
jdbc:odbc:allandb
PreparedStatement接口:
預編譯的sql語句對象
做用: 解決了書寫sql語句時一些特殊的字符與sql保留字符衝突的問題,很是方便
/**
*知識點:
*PreparedStatement接口及方法的使用
*程序目標:
*java文件:
*PreparedInsert.java:鏈接數據庫,插入一條數據
*JdbcUtil.java:實現一個工具類,功能:1.鏈接數據庫 2.關閉資源
*/
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){
}
}
}
數據庫的增刪改查的例子:
/**
*知識點:
*JDBC+SQL+ORACLE
*程序目標:
*UserDao.java:實現了數據庫的增刪改查
*JdbcUtil.java:工具類,有連庫和關閉資源的方法
*/
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();
}
}
一些經常使用的方法:
/**
*知識點:
*execute方法,getResultSet(),getUpdateCount()
*程序目標:
*JdbcUtil.java:工具類,鏈接數據庫,關閉資源
*sqlExecutor.java:命令行參數輸入sql語句,並執行該語句
*/
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. 補充
JDBC鏈接MySQL
加載及註冊JDBC驅動程序
Class.forName("com.mysql.jdbc.Driver");
Class.forName("com.mysql.jdbc.Driver").newInstance();
JDBC URL 定義驅動程序與數據源之間的鏈接
標準語法:
<protocol(主要通信協議)>:<subprotocol(次要通信協議,即驅動程序名稱)>:<data source identifier(數據源)>
MySQL的JDBC URL格式:
jdbc:mysql//[hostname][:port]/[dbname][?param1=value1][¶m2=value2]….
示例:jdbc:mysql://localhost:3306/sample_db?user=root&password=your_password
常見參數:
user 用戶名
password 密碼
autoReconnect 聯機失敗,是否從新聯機(true/false)
maxReconnect 嘗試從新聯機次數
initialTimeout 嘗試從新聯機間隔
maxRows 傳回最大行數
useUnicode 是否使用Unicode字體編碼(true/false)
characterEncoding 何種編碼(GB2312/UTF-8/…)
relaxAutocommit 是否自動提交(true/false)
capitalizeTypeNames 數據定義的名稱以大寫表示
創建鏈接對象
String url="jdbc:mysql://localhost:3306/sample_db?user=root&password=your_password";
Connection con = DriverManager.getConnection(url);
創建SQL陳述式對象(Statement Object)
Statement stmt = con.createStatement();
執行SQL語句
executeQuery()
String query = "select * from test";
ResultSet rs=stmt.executeQuery(query);
結果集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類型 技術手冊P421
PreparedStatement(預編語句)
PreparedStatement stmt = conn.prepareStatement("insert into test(id,name)values(?,?)");
stmt.setInt(1,id);
stmt.setString(2,name);
注:一旦設定語句的參數值後,就能夠屢次執行改語句,直到調用clearParameters()方法將他清除爲止
CallableStatement(預儲程序)技術手冊P430
JDBC2.0使用
ResultSet對象中的光標上下自由移動
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 能夠上下移動,能夠取得改變後的值。
TYPE_SCROLL_INSENSITIVE 能夠上下移動。
resultSetConcuttency
CONCUR_READ_ONLY 只讀
CONCUR_UPDATABLE ResultSet對象能夠執行數據庫的新增、修改、和移除
直接使用ResultSet對象執行更新數據
新增數據
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;
更新數據
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;
刪除數據
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); 關閉自動承認模式
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(); 沒有任何錯誤,執行批處理stmt.executeBatch();
JNDI-數據源(Data Source)與鏈接池(Connection Pool)
Tomcat的JDBC數據源設置 技術手冊P439
鏈接池工具-Proxool Var 0.8.3 技術手冊P446
設置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>
後端統計端口添加下列
<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 後端統計接口添加此行
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);
使用JDBC時,咱們都會很天然得使用下列語句:
[java] view plaincopyprint?
爲何說很天然呢,由於不管是網上仍是書本教程上得例子都是這樣的,並且程序也確實正常運行了,因而你們也就問心無愧的找葫蘆畫瓢下去了。
必定要有這一句嗎?不是的,咱們徹底能夠用這樣一句代替它:
[java] view plaincopyprint?
你們可能都看出個大概來了,咱們只須要在調用DriverManager的getConnection方法以前,保證相應的Driver類已經被加載到jvm中,而且完成了類的初始化工做就好了,而具體是怎樣實現這個功能倒是沒有講究的。
談到類的初始化,這裏不得不提,在什麼樣的狀況下類纔可以初始化?
上面兩種方法均可以實現這個功能,所以程序能夠正常運行。注意了,若是咱們進行以下操做,程序是不能正常運行的,由於這樣僅僅使Driver類被裝載到jvm中,卻沒有進行相應的初始化工做。具體關於類的加載和初始化詳細,能夠閱讀個人這篇博文《JVM虛擬機和類加載器》。
[java] view plaincopyprint?
咱們都知道JDBC是使用Bridge模式進行設計的,DriverManager就是其中的Abstraction,java.sql.Driver是Implementor,com.mysql.jdbc.Driver是Implementor的一個具體實現(請參考GOF的Bridge模式的描述)。你們注意了,前一個Driver是一個接口,後者倒是一個類,它實現了前面的Driver接口。
Bridge模式中,Abstraction(DriverManager)是要擁有一個Implementor(Driver)的引用的,可是咱們在使用過程當中,並無將Driver對象註冊到DriverManager中去啊,這是怎麼回事呢?jdk文檔對Driver的描述中有這麼一句:
When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager
哦,原來是com.mysql.jdbc.Driver在裝載完後自動幫咱們完成了這一步驟。源代碼是這樣的:
[java] view plaincopyprint?
能夠看到DriveManager裏面定義了靜態方法,而mysql等驅動類都是內部用靜態數據塊的方式來初始化,完成Driver對象註冊到DriverManager中,因此只要jvm裝載了這些驅動類就會將Driver對象註冊到DriverManager中去(Class.forName(xxx.xx.xx) 返回的是一個類;Class.forName(xxx.xx.xx);的做用是要求JVM查找並加載指定的類,也就是說JVM會執行該類的靜態代碼段 。靜態代碼是和class綁定的,class裝載成功就表示執行了你的靜態代碼了。並且之後不會再走這段靜態代碼了。),後面就能夠直接使用了。