JavaEE之JDBC編程[詳解]

1.數據庫簡介html

數據庫(DB,Data Base )java

數據庫管理系統(DBMS,Data Base Management System)mysql

關係型數據庫(RDB)sql

關係型數據庫管理系統(RDBMS)數據庫

SQL語言(Structured Query Language):使用關係模型的數據庫語言,用於和各種數據庫的交互,提供通用的數據管理和查詢功能。編程

經常使用SQL指令:(CURD)tomcat

SELECT 、INSERT、DELETE、UPDATE、CREATE、DROP服務器

ODBC(Open DataBase Connectivity,開放式數據庫互連):數據庫系統應用程序接口規範。網絡

支持應用程序以標準的ODBC函數和SQL語句操做各類不一樣類型的數據庫。併發

1

 

2.JDBC(Java DataBase Connectivity)

JDBC功能:

①支持基本SQL語句,在Java程序中實現數據庫操做功能並簡化操做過程

②提供多樣化的數據庫鏈接方法

③爲各類不一樣的數據庫提供統一的操做界面

JDBC API:

java.sql. DriverManager類:驅動管理類

java.sql.Driver接口

java.sql.Connection接口:與特定的數據庫之間的鏈接

java.sql.Statement接口:指定數據庫鏈接和要執行的sql表達式就能夠執行sql語句

java.sql.ResultSet接口:返回結果

 

原理:首先要將不一樣的數據庫驅動程序加載到驅動程序管理器

2

 

3.JDBC驅動程序

數據庫驅動程序(DataBase Driver)

JDBC驅動程序分類:

第一類:JDBC-OCBC橋(並不經常使用)

第二類:Java到本地API(本地API是指本機安裝了目標數據庫的客戶端,可是不通用,由於必需要安裝客戶端)

第三類:Java到網絡協議(經過網絡協議實現數據庫操做,服務器端須要有特定的協議)

第四類:Java到數據庫協議(速度最快,可是不具有通用性,必需要爲各類數據庫配置相應的協議)

 

4.數據庫URL

JDBC技術中使用數據庫URL來標識目標數據庫      數據庫URL格式:jdbc:<子協議名>:<子名稱>

"jdbc"爲協議名,肯定不變;

<子協議名>指定目標數據庫的種類和具體鏈接方式;

<子名稱>指定具體的數據庫/數據源鏈接信息(如數據庫服務器的IP地址/通訊端口號、ODBC數據源名稱、鏈接用戶名/密碼等)。

子名稱的格式和內容隨子協議的不一樣而改變。

舉例:

jdbc:oracle:thin:@166.111.78.98:1521:ora9

jdbc:microsoft:sqlserver://127.0.0.1:1433

jdbc:microsoft:sqlserver://127.0.0.1:1433;databasename=pubs

 

關於oracle的thin和oci的方式訪問的區別請見:http://www.cnblogs.com/phoebus0501/archive/2011/05/12/2044725.html

 

5.JDBC編程基本步驟

1. 加載 驅 動 程 序 ( 向 系 統 注 冊 所 需 的 JDBC 驅 動 程序);

2. 創建到指定數據庫的鏈接;

3. 提交數據庫查詢;

4. 取得查詢結果

 

MySQL 數據庫的一個簡單實例:

package v512.chap18;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class JDBCExample { public static void main(String[] args) { try { Class.forName("org.gjt.mm.mysql.Driver"); String url ="jdbc:mysql://localhost/blog"; Connection connection = DriverManager.getConnection(url,"root","yinger"); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("select id,title from blog"); while (resultSet.next()) { System.err.println(resultSet.getInt("id")+":"+resultSet.getString("title")); } resultSet.close(); statement.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); } } }

轉載: java鏈接常見數據庫的鏈接字符串

1. MySQL(http://www.mysql.com)mm.mysql-2.0.2-bin.jar
Class.forName( "org.gjt.mm.mysql.Driver" ); cn = DriverManager.getConnection( "jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName", sUsr, sPwd ); 2. PostgreSQL(http://www.de.postgresql.org)pgjdbc2.jar Class.forName( "org.postgresql.Driver" ); cn = DriverManager.getConnection( "jdbc:postgresql://MyDbComputerNameOrIP/myDatabaseName", sUsr, sPwd ); 3. Oracle(http://www.oracle.com/ip/deploy/database/oracle9i/)classes12.zip Class.forName( "oracle.jdbc.driver.OracleDriver" ); cn = DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd ); 例如: Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:orcale"; conn = DriverManager.getConnection(url,"scott","tiger"); 4. Sybase(http://jtds.sourceforge.net)jconn2.jar Class.forName( "com.sybase.jdbc2.jdbc.SybDriver" ); cn = DriverManager.getConnection( "jdbc:sybase:Tds:MyDbComputerNameOrIP:2638", sUsr, sPwd ); // (Default-Username/Password: "dba"/"sql") 5. Microsoft SQLServer(http://jtds.sourceforge.net) Class.forName( "net.sourceforge.jtds.jdbc.Driver" ); cn = DriverManager.getConnection( "jdbc:jtds:sqlserver://MyDbComputerNameOrIP:1433/master", sUsr, sPwd ); 6. Microsoft SQLServer(http://www.microsoft.com) Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" ); cn = DriverManager.getConnection( "jdbc:microsoft:sqlserver://MyDbComputerNameOrIP:1433;databaseName=master", sUsr, sPwd ); 7. ODBC Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" ); Connection cn = DriverManager.getConnection( "jdbc:odbc:" + sDsn, sUsr, sPwd ); 8.DB2 Class.forName("Com.ibm.db2.jdbc.net.DB2Driver"); String url="jdbc:db2://192.9.200.108:6789/SAMPLE" cn = DriverManager.getConnection( url, sUsr, sPwd );

 

6.左圖是 ResultSet的getXXX()方法,右圖是SQL和Java的類型對應關係

3                          4

 

7.獲取數據庫元數據

數據庫元數據:數據庫的相關信息

實例:

package v512.chap18;
import java.sql.*;
public class TestMetaData{ public static void main(String args[]){ Connection conn = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:orcale"; conn = DriverManager.getConnection(url,"scott","tiger"); ResultSet rs = null; DatabaseMetaData dmd = conn.getMetaData(); if (dmd == null) { System.out.println ("No Meta available"); } else { System.out.println ("數據庫名稱:" + dmd.getDatabaseProductName()); System.out.println ("數據庫版本:" + dmd.getDatabaseProductVersion()); System.out.println ("數據庫驅動程序:" + dmd.getDriverName()); System.out.println ("驅動程序版本號:" + dmd.getDriverVersion()); System.out.println ("併發訪問的用戶個數" + dmd.getMaxConnections()); System.out.println ("數據類型列表:" ); rs = dmd.getTypeInfo(); while(rs.next()){ System.out.println("\t" + rs.getString(1)); } rs.close(); } Statement stmt = conn.createStatement(); String s = "select * from dept"; rs = stmt.executeQuery(s); System.out.println("數據表dept結構信息:"); ResultSetMetaData rsm = rs.getMetaData(); int columnCount = rsm.getColumnCount(); System.out.println("列序號\t列名\t數據類型"); for(int i=1;i<=columnCount;i++){ System.out.println(" " + i + " \t" + rsm.getColumnName(i) + "\t" + rsm.getColumnTypeName(i)); } rs.close(); stmt.close(); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(conn != null && !conn.isClosed()){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } }

返回的結果:

數據庫名稱:Oracle
數據庫版本:Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
數據庫驅動程序:Oracle JDBC driver
驅動程序版本號:11.2.0.1.0
併發訪問的用戶個數0
數據類型列表:
    INTERVALDS
    INTERVALYM
    TIMESTAMP WITH LOCAL TIME ZONE
    TIMESTAMP WITH TIME ZONE
    NUMBER
    NUMBER
    NUMBER
    LONG RAW
    RAW
    LONG
    CHAR
    NUMBER
    NUMBER
    NUMBER
    FLOAT
    REAL
    VARCHAR2
    DATE
    DATE
    TIMESTAMP
    STRUCT
    ARRAY
    BLOB
    CLOB
    REF
數據表dept結構信息:
列序號    列名    數據類型
 1     DEPTNO    NUMBER
 2     DNAME    VARCHAR2
 3     LOC    VARCHAR2

8.訪問SQL Server數據庫

準備SQL Server數據庫JDBC驅動程序

1. 從微軟網站下載JDBC驅動程序安裝文件

2. 本地安裝該驅動程序包

3. 從新設置CLASSPATH環境變量

 

 

9.JDBC-ODBC編程

工做原理:

JDBC驅動程序管理器並不直接操縱數據庫驅動程序,而是調用JDBC-ODBC 橋驅動程序操縱ODBC 驅動程序,進而鏈接各類類型的數據庫。

JDBC驅動程序  -> JDBC-ODBC 橋驅動程序  -> ODBC 驅動程序  -> 各類類型的數據庫   [能夠結合上面的幾幅圖來理解]

能夠封裝不少的數據庫或者數據文件:excel,access,SQL Server。。。

編程步驟:

第一步:建立ODBC數據源  (在Windows操做系統中把目標數據庫封裝成ODBC數據源)

找到 ODBC

5

 

配置好一個 ODBC 數據源

7

 

第二步:在程序中鏈接並操做ODBC數據源

package v512.chap18;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class ODBCExample { public static void main(String[] args) { try { Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" ); Connection connection = DriverManager.getConnection("jdbc:odbc:MyExcelODBC1"); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("select * from [Sheet1$]"); while (resultSet.next()) {//注意,索引是從1開始的,不然報錯:[Microsoft][ODBC 驅動程序管理器] 無效的描述器索引 System.out.println("name:"+resultSet.getString(1)+"---tel:"+resultSet.getString(2)); } resultSet.close(); statement.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); } } }

Excel文件中的內容:

8

 

程序運行輸出結果:

name:yinger---tel:15079576419.0
name:胡吉清---tel:13707950937.0
name:劉明---tel:13842879813.0
name:小熊強---tel:15244672815.0
name:朱思瑞---tel:13920137236.0
name:馬繼鳴---tel:13548607626.0
name:魏紀元---tel:13739068492.0
name:王晨龍---tel:13807493710.0
name:王沛東---tel:13875803565.0
name:楊陽---tel:13875810771.0
name:鄒星乾---tel:13875960663.0
name:劉龍---tel:13875831389.0
name:易兵---tel:13875995083.0
name:張華敏---tel:13875972761.0
name:楊穎華---tel:13875953921.0
name:張丹羊---tel:15873116080.0
name:大哥---tel:13720254940.0

除了末尾多了個.0以外其餘的數據都是沒有問題的!

 

10.使用屬性文件配置環境

將數據庫鏈接信息(URL、用戶名/密碼等)保存到專門的屬性文件中,而不在程序中直接給出

屬性文件:

#Mysql db info
db_url = jdbc:mysql://localhost/blog
username = root
password = root

測試類:

package v512.chap18;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class JDBCExample { public static void main(String[] args) { try { Class.forName("org.gjt.mm.mysql.Driver"); // //直接編寫獲得鏈接 String url ="jdbc:mysql://localhost/blog"; // Connection connection = DriverManager.getConnection(url,"root","root"); //讀取配置文件獲得鏈接 Properties properties = new Properties(); FileInputStream fileInputStream = new FileInputStream("E:\\mydb.properties"); properties.load(fileInputStream); // String url = properties.getProperty("db_url"); System.out.println(url); String username = properties.getProperty("username"); System.out.println(username); String password = properties.getProperty("password"); System.out.println(password); Connection connection = DriverManager.getConnection(url,username,password); //進行數據查詢 Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("select id,title from blog"); while (resultSet.next()) { System.out.println(resultSet.getInt("id")+":"+resultSet.getString("title")); } resultSet.close(); statement.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); } } }

 

輸出結果:

jdbc:mysql://localhost/blog
root
root
1:I love Java
10:Java JSP
11:Java Servlet
12:Java Spring
14:cnblog
16:very good
17:500 tomcat

11.OCI方式訪問Oracle

什麼是OCI(Oracle Call Interface)方式?

OCI方式鏈接時Oracle客戶端配置的三種方式:

1.使用Net Configuration Assistant

2.使用Net Manager圖形化工具

3.直接修改數據庫配置文件"tnsnames.ora"  (個人電腦的路徑:D:\app\Administrator\product\11.2.0\dbhome_1\NETWORK\ADMIN\tnsnames.ora)

 

9                      10

 

12.可滾動/可更新結果集

結果集類型

不可滾動(FORWARD_ONLY)

滾動不敏感(SCROLL_INSENSITIVE):能夠滾動,可是若是數據庫中的數據發生了更改不會反映到結果集中

滾動敏感(SCROLL_SENSITIVE)

結果集的併發模式

只讀的(READ_ONLY)

可更新的(UPDATABLE):容許對結果集進行更改,修改或者刪除,而且能夠將它反應到數據庫中

Connection接口中提供的重載方法createStatement()用於獲取可滾動/可更新結果集。

方法格式:Statement createStatement(int type, int concurrency)

注意:以上結果集的類型和併發模式受到具體的數據庫和數據庫驅動程序的限制

11

 

可使用數據庫元數據進行測試:

import java.sql.*;
public class TestMetaData{ public static void main(String args[]){ Connection conn = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:orcale"; conn = DriverManager.getConnection(url,"scott","tiger"); ResultSet rs = null; DatabaseMetaData dmd = conn.getMetaData(); if (dmd == null) { System.out.println ("No Meta available"); } else { System.out.println ("數據庫名稱:" + dmd.getDatabaseProductName()); System.out.println ("數據庫版本:" + dmd.getDatabaseProductVersion()); System.out.println ("數據庫驅動程序:" + dmd.getDriverName()); System.out.println ("驅動程序版本號:" + dmd.getDriverVersion()); System.out.println ("--------------------------------------------"); System.out.println ("結果集類型及支持狀況(true-支持,false-不支持)"); System.out.println ("TYPE_FORWARD_ONLY: " + dmd.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY)); System.out.println ("TYPE_SCROLL_INSENSITIVE: " + dmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE)); System.out.println ("TYPE_SCROLL_SENSITIVE: " + dmd.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE)); System.out.println ("CONCUR_READ_ONLY: " + dmd.supportsResultSetType(ResultSet.CONCUR_READ_ONLY)); System.out.println ("CONCUR_UPDATABLE: " + dmd.supportsResultSetType(ResultSet.CONCUR_UPDATABLE)); } }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(conn != null){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } }

使用可滾動結果集

(1)對於可滾動結果集,可使用ResultSet 接口中定義的下述方法進行遍歷

boolean next()

boolean previous()

boolean first()

boolean last()

void beforeFirst():第一個的前面,在調用next就是第一個了

void afterLast():最後一個的後面

boolean relative(int rows):相對的移動必定的行數,負數是向前

boolean absolute(int row):絕對移動,移動到某一行

int getRow()

 

測試方法:
import java.sql.*;
public class TestScrollResultSet{ public static void main(String args[]){ Connection conn = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:ora9"; conn = DriverManager.getConnection(url,"scott","tiger"); Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet rs = stmt.executeQuery("select * from student"); while(rs.next()){ showOneRow(rs); } System.out.println("-----------"); rs.last(); showOneRow(rs); rs.first(); showOneRow(rs); rs.beforeFirst(); rs.next(); showOneRow(rs); rs.absolute(2); showOneRow(rs); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(conn != null){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } public static void showOneRow(ResultSet rs) throws SQLException{ System.out.print("第" + rs.getRow() + "行: "); System.out.print(rs.getString(1)); System.out.print("\t" + rs.getString(2)); System.out.print("\t" + rs.getString(3)); System.out.println(); } }

 

(2)對於可更新結果集,可使用ResultSet 接口中定義的下述方法進行更新操做

void updateXXX(String columnName, XXX x)

void updateXXX(int columnIndex, XXX x)

void updateRow():它必須緊跟在上面的方法以後

void moveToInsertRow():在當前的結果集中插入一行,至關於newRow,而後調用updateXXX()和insertRow方法就能夠在數據庫中插入一行數據

void insertRow()

void moveToCurrentRow():若是當前是在插入一行記錄,調用這個方法能夠將遊標返回到剛纔指向的行

void deleteRow()

void cancelRowUpdates()

 

測試方法:

import java.sql.*;
public class TestUpdatableResultSet{ public static void main(String args[]){ Connection conn = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:ora9"; conn = DriverManager.getConnection(url,"scott","tiger"); Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("select tid,name,salary from teacher"); //ResultSet rs = stmt.executeQuery("select teacher.* from teacher"); //更新前結果集中數據 while(rs.next()){ showOneRow(rs); } //更新和刪除記錄 rs.beforeFirst(); while(rs.next()){ String name = rs.getString("name").trim(); if(name.equals("李四")){ double sal = rs.getDouble("salary"); rs.updateDouble("salary", sal + 8888); rs.updateRow(); }else if(name.equals("張三")){ rs.deleteRow(); } } //插入新記錄 rs.moveToInsertRow(); rs.updateInt("tid",1005); rs.updateString("name","雲飛揚"); rs.updateDouble("salary",2840); rs.insertRow(); rs.close(); //結果集更新後後數據庫中數據 System.out.println("--------------------------------------------"); rs = stmt.executeQuery("select * from teacher"); while(rs.next()){ showOneRow(rs); } rs.close(); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(conn != null){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } public static void showOneRow(ResultSet rs) throws SQLException{ System.out.print("第" + rs.getRow() + "行: "); System.out.print(rs.getInt(1)); System.out.print("\t" + rs.getString(2)); System.out.print("\t" + rs.getDouble(3)); System.out.println(); } }

 

【注意】在實際的開發中並不建議在結果集中進行數據操做而後同步到數據庫中

 

13.預處理語句 PreparedStatement

java.sql.PreparedStatement 接口提供了執行預編譯SQL語句的功能,它繼承了java.sql.Statement接口。

Connection對象的prepareStatement(String sql)方法可建立並返回PreparedStatement對象。

PreparedStatement接口主要方法:

void setXXX(int parameterIndex, XXX x)

ResultSet executeQuery()

int executeUpdate()

 

實例:

package v512.chap18;

import java.sql.*;

public class PrepStmt { public static void main(String[] args) { Connection con = null; PreparedStatement pst = null; try { Class.forName("org.gjt.mm.mysql.Driver"); String url = "jdbc:mysql://localhost/blog"; con = DriverManager.getConnection(url, "root", "root"); String sql = "insert into blog(categoryid,title,content,created_time) values(?,?,?,?)"; pst = con.prepareStatement(sql); pst.setInt(1, 1); pst.setString(2, "Java vs C#"); pst.setString(3, "Java is better than C#"); pst.setDate(4, new Date(2010, 8, 8)); pst.executeUpdate(); System.out.println("id\ttitle\tcreateTime"); pst = con.prepareStatement("select id,title,created_time from blog where id = ?"); pst.setInt(1, 1); ResultSet rs = pst.executeQuery(); if (rs.next()) { System.out.println(rs.getInt(1) + "\t" + rs.getString(2).trim() + "\t" + rs.getDate(3)); } } catch (Exception e) { System.err.println(e); } finally { try { if (pst != null) { pst.close(); } } catch (Exception e) { e.printStackTrace(); } try { if (con != null) { con.close(); } } catch (Exception e) { e.printStackTrace(); } } } }

輸出結果:

id    title    createTime
1    I love Java    2011-05-11

 

數據庫中也有相應的數據被插入了,只是程序的設值不合理。。。

12

 

 

14.調用存儲過程

java.sql.CallableStatement接口提供了調用數據庫服務器端存儲過程(Procedure)的功能,它繼承了java.sql. PreparedStatement接口。

Connection 對象的prepareCall(String sql) 方法可建立並返回CallableStatement對象。

CallableStatement接口主要方法:

void setXXX(int parameterIndex, XXX x)

boolean execute()

採用存儲過程能夠提升系統的運行效率,可是在數據庫移植的時候會產生一些錯誤或者加劇移植的操做任務

實例:

首先創建一個存儲過程:

drop procedure MyProcedure; drop table person; create table person(id number primary key, name char(20), age number); create or replace procedure MyProcedure (pid in number,name in char,age in char) as begin insert into person values(pid,name,age); end; /

 

測試類:

import java.sql.*;
public class CallStmt{ public static void main(String[] args){ Connection con = null; CallableStatement cst = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:ora9"; con = DriverManager.getConnection(url,"scott","tiger"); cst = con.prepareCall("{call MyProcedure(?,?,?)}"); cst.setInt(1,1001); cst.setString(2,"Jenny"); cst.setInt(3,48); cst.execute(); cst.close(); }catch(Exception e){ System.err.println(e); }finally{ try{ if(con != null){ con.close(); } }catch(Exception e){ e.printStackTrace(); } } } }

 

15.事務處理

(1)和數據庫中的事務管理模式相對應,JDBC 中的Connection對象也可分爲自動提交和非自動提交兩種模式。

JDBC驅動程序的默認事務管理模式爲"自動提交"。

Connection接口提供的事務處理相關方法:

void setAutoCommit(boolean autoCommit):默認是true

boolean getAutoCommit():獲得當前的提交方式

void commit():commit和rollback是在關閉了自動提交時纔會有的方法

void rollback()

 

測試實例:

import java.sql.*;

public class TestCommit{ public static void main(String args[]){ Connection conn = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url="jdbc:oracle:thin:@127.0.0.1:1521:ora9"; conn=DriverManager.getConnection(url,"scott","tiger"); boolean autoCommit = conn.getAutoCommit(); // 關閉自動提交功能 conn.setAutoCommit(false); Statement stmt=conn.createStatement(); stmt.executeUpdate("insert into dept values (77,'Market','Beijing')"); stmt.executeUpdate("insert into dept values (88,'R&D','Shanghai')"); ResultSet rs=stmt.executeQuery("select * from dept"); while(rs.next()){ System.out.print("DeptNo: "+rs.getInt(1)); System.out.print("\tDeptName: "+rs.getString(2)); System.out.println("\tLOC: "+rs.getString(3)); } // 提交事務 conn.commit(); // 恢復原來的提交模式 conn.setAutoCommit(autoCommit); stmt.close(); }catch(Exception e){ System.out.println("操做失敗、任務撤消!"); try{ // 回滾、取消前述操做 conn.rollback(); }catch(Exception e1){ e.printStackTrace(); } }finally{ try{ if(conn != null){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } }

 

(2)事務處理之部分回滾

JDBC3.0 開 始 支 持 在 事 務 中 使 用 保 存 點(Savepoint),以實現對數據庫事務的進一步控制、即支持部分回滾功能。

java.sql.Savepoint接口表示數據庫事務中的保存點。

在Connection對象的rollback()方法中能夠對當前事中的保存點進行引用,從而將事務回滾到該保存點。

在保存點以前的更新操做能生效,可是以後的更新不生效。

 

代碼實例:

import java.sql.*;
public class TestSavepoint{ public static void main(String[] args){ Connection conn = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:ora9"; conn = DriverManager.getConnection(url,"scott","tiger"); conn.setAutoCommit(false); Statement stmt = conn.createStatement(); stmt.executeUpdate("insert into teacher values(11,'Tom',2500)"); stmt.executeUpdate("insert into teacher values(12,'John',3400)"); Savepoint sp1 = conn.setSavepoint("p1"); stmt.executeUpdate("insert into teacher values(13,'Billy',3150)"); Savepoint sp2 = conn.setSavepoint("p2"); stmt.executeUpdate("update teacher set salary = salary+8888 where tid = 12"); ResultSet rs = stmt.executeQuery("select avg(salary) from teacher"); rs.next(); double avg_sal = rs.getDouble(1); if(avg_sal > 4000){ conn.rollback(sp1); }else if(avg_sal >= 3000){ conn.rollback(sp2); } conn.commit(); rs = stmt.executeQuery("select * from teacher"); while(rs.next()){ System.out.println(rs.getInt(1) + "\t" + rs.getString(2).trim() + "\t" + rs.getDouble(3)); } rs.close(); stmt.close(); }catch(Exception e){ System.out.println("Failure,rollback!"); try{ conn.rollback(); }catch(Exception e1){ e.printStackTrace(); } e.printStackTrace(); }finally{ try{ if(conn != null){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } }

 

16.批處理

JDBC2.0 開 始 提 供 了 對 數 據 庫 操 做 的 批 處 理(Batch Processing)功能,使用批處理功能避免了向數據庫進行一連串的調用,

從而能夠顯著提升程序的運行效率。

Statement接口提供的批處理相關方法:

void addBatch(String sql)

int[] executeBatch()

void clearBatch()

 

實例代碼:

import java.sql.*;
public class TestBatch{ public static void main(String[] args){ Connection conn = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:ora9"; conn = DriverManager.getConnection(url,"scott","tiger"); conn.setAutoCommit(false); Statement stmt = conn.createStatement(); stmt.addBatch("insert into teacher values(11,'Tom',2500)"); stmt.addBatch("insert into teacher values(12,'John',3400)"); stmt.addBatch("insert into teacher values(13,'Billy',3150)"); stmt.addBatch("update teacher set salary = salary + 88"); stmt.executeBatch(); conn.commit(); ResultSet rs = stmt.executeQuery("select * from teacher"); while(rs.next()){ System.out.println(rs.getInt(1) + "\t" + rs.getString(2).trim() + "\t" + rs.getDouble(3)); } rs.close(); stmt.close(); }catch(Exception e){ System.out.println("Failure,rollback!"); try{ conn.rollback(); }catch(Exception e1){ e.printStackTrace(); } e.printStackTrace(); }finally{ try{ if(conn != null){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } }

 

17.高級SQL類型   BLOB/CLOB

BLOB(Binary Large OBject,二進制大對象)類型用於保存大規模的二進制數據

CLOB(Character Large OBject,文本大對象)類型則用於保存大規模的文本數據

JDBC2.0開始引入了對應於SQL99標準的多種高級數據類型,其中最重要的是兩種大對象類型BLOB和CLOB

要在Oracle數據庫中使用這兩種大對象類型必需要使用高版本的數據庫驅動程序

 

測試實例:

保存Blob

import java.sql.*;
import java.io.*;

public class SavePicture{ public static void main(String[] args){ Connection conn = null; PreparedStatement stmt = null; FileInputStream fis = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:ora9"; conn = DriverManager.getConnection(url, "scott","tiger"); String sql = "insert into Student_List values(?,?,?)"; stmt=conn.prepareStatement(sql); stmt.setString(1,"s01"); stmt.setString(2,"Youyou"); File file = new File("yy.jpg"); fis = new FileInputStream(file); stmt.setBinaryStream(3, fis, (int)file.length()); stmt.executeUpdate(); stmt.close(); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(fis!=null){ fis.close(); } }catch(IOException ioe){ ioe.printStackTrace(); } try{ if(conn != null){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } }

 

獲得BLOB

import java.sql.*;
import java.io.*;

public class GetPicture{ public static void main(String[] args){ PreparedStatement stmt = null; ResultSet rs = null; Connection conn = null; FileOutputStream fos = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url= "jdbc:oracle:thin:@localhost:1521:ora9"; conn = DriverManager.getConnection(url,"scott","tiger"); String sql="select * from Student_List where Student_ID='s01'"; stmt = conn.prepareStatement(sql); rs = stmt.executeQuery(); rs.next(); File file = new File("d:\\kk.jpg"); fos = new FileOutputStream(file); InputStream is = rs.getBinaryStream(3); int len = 0; byte b[] = new byte[4*1024]; while((len=is.read(b))!=-1) { fos.write(b,0,len); } fos.flush(); fos.close(); is.close(); rs.close(); stmt.close(); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(fos!=null){ fos.close(); } }catch(IOException ioe){ ioe.printStackTrace(); } try{ if(conn != null){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } }

 

保存CLOB

import java.sql.*;
import java.io.*;

public class SaveClob{ public static void main(String[] args){ Connection conn = null; PreparedStatement stmt = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:ora9"; conn = DriverManager.getConnection(url, "scott","tiger"); String sql = "insert into book_list values(?,?,?)"; stmt=conn.prepareStatement(sql); stmt.setString(1,"b001"); stmt.setString(2,"99個簡單法則"); BufferedReader br = new BufferedReader(new FileReader("a.txt")); StringBuffer sb = new StringBuffer(); String s; while((s=br.readLine()) != null){ sb.append(s + "\n"); } br.close(); String content = sb.toString(); StringReader sr = new StringReader(content); stmt.setCharacterStream(3, sr, content.length()); stmt.executeUpdate(); sr.close(); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(conn != null){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } }

獲得CLOB

import java.sql.*;
import java.io.*;

public class GetClob{ public static void main(String[] args){ Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; FileOutputStream fos = null; try{ Class.forName("oracle.jdbc.driver.OracleDriver"); String url= "jdbc:oracle:thin:@localhost:1521:ora9"; conn = DriverManager.getConnection(url,"scott","tiger"); String sql="select * from book_list where bid='b001'"; stmt = conn.prepareStatement(sql); rs = stmt.executeQuery(); rs.next(); StringBuffer sb = new StringBuffer(); Reader rd = rs.getCharacterStream(3); BufferedReader br = new BufferedReader(rd); String s; while((s=br.readLine())!=null) { sb.append(s + "\n"); } System.out.println(sb.toString()); rs.close(); br.close(); stmt.close(); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(conn != null){ conn.close(); } }catch(Exception e){ e.printStackTrace(); } } } }
相關文章
相關標籤/搜索