1. blob欄位java如何處理
1.使用中的方法進行傳輸。在ResultSet 中有getBlob()方法,在PreparedStatement中有setBlob()方法,所以大多數人都會嘗試setBlob
(),getBlob() 進行讀寫,或者兩個資料庫之間BLOB的傳輸。這種方法實際上是行不通的,據網上的一些資料介紹,說sun官方的文檔有些方法
都是錯誤的。
2.使用ResultSet.getBinaryStream 和PreparedStatement.setBinaryStream對BLOB進行讀寫或兩個資料庫間的傳輸。這種方法我自己嘗試過,
發現,如果BLOB中存儲的是文本文件的話,就沒問題,如果是二進制文件,傳輸就會有問題。
根據自己的經驗,以及查閱了Oracle的官方文檔,都是使用如下處理方法:
1.新建記錄,插入BLOB數據
1.1首先新建記錄的時候,使用oracle的函數插入一個空的BLOB,假設欄位A是BLOB類型的:
insert xxxtable(A,B,C) values(empty_blob(),'xxx','yyyy')
1.2後面再查詢剛才插入的記錄,然後更新BLOB,在查詢前,注意設置Connection的一個屬性:
conn.setAutoCommit(false);如果缺少這一步,可能導致fetch out of sequence等異常.
1.3 查詢剛才插入的記錄,後面要加「 for update 」,如下:
select A from xxxtable where xxx=999 for update ,如果缺少for update,可能出現row containing the LOB value is not locked
的異常
1.4 從查詢到的 BLOB欄位中,獲取blob並進行更新,代碼如下:
BLOB blob = (BLOB) rs.getBlob("A");
OutputStream os = blob.getBinaryOutputStream();
BufferedOutputStream output = new BufferedOutputStream(os);
後面再使用output.write方法將需要寫入的內容寫到output中就可以了。例如我們將一個文件寫入這個欄位中:
BufferedInputStream input = new BufferedInputStream(new File("c://hpWave.log").toURL().openStream());
byte[] buff = new byte[2048]; //用做文件寫入的緩沖
int bytesRead;
while(-1 != (bytesRead = input.read(buff, 0, buff.length))) {
output.write(buff, 0, bytesRead);
System.out.println(bytesRead);
}
上面的代碼就是從input里2k地讀取,然後寫入到output中。
1.5上面執行完畢後,記得關閉output,input,以及關閉查詢到的ResultSet
1.6最後執行conn.commit();將更新的內容提交,以及執行conn.setAutoCommit(true); 改回Connction的屬性
2.修改記錄,方法與上面的方法類似,
2.1首先更新BLOB以外的其他欄位
2.2 使用1.3中類似的方法獲取記錄
2.3 修改的過程中,注意以下:a 需要更新的記錄中,BLOB有可能為NULL,這樣在執行blob.getBinaryOutputStream()獲取的值可能為
null,那麼就關閉剛才select的記錄,再執行一次update xxxtable set A = empty_blob() where xxx, 這樣就先寫入了一個空的BLOB(不是null),然後再
使用1.3,1.4中的方法執行更新記錄.b 注意別忘了先執行setAutoCommit(false),以及"for update",以及後面的conn.commit();等。
3.讀取BLOB欄位中的數據.
3.1 讀取記錄不需要setAutoCommit(),以及 select ....for update.
3.2 使用普通的select 方法查詢出記錄
3.3 從ResultSet中獲取BLOB並讀取,如下:
BLOB b_to = (BLOB) rs.getBlob("A");
InputStream is = b_from.getBinaryStream();
BufferedInputStream input = new BufferedInputStream(is);
byte[] buff = new byte[2048];
while(-1 != (bytesRead = input.read(buff, 0, buff.length))) {
//在這里執行寫入,如寫入到文件的BufferedOutputStream里
System.out.println(bytesRead);
}
通過循環取出blob中的數據,寫到buff里,再將buff的內容寫入到需要的地方
4.兩個資料庫間blob欄位的傳輸
類似上面1和3的方法,一邊獲取BufferedOutputStream,另外一邊獲取BufferedInputStream,然後讀出寫入,需要注意的是寫入所用的
Connection要執行conn.setAutoCommit(false);以及獲取記錄時添加「 for update 」以及最後的commit();
總結以上方法,其根本就是先創建空的BLOB,再獲取其BufferedOutputStream進行寫入,或獲取BufferedInputStream進行讀取
(1)對資料庫clob型執行插入操作
*************************************************
java.sql.PreparedStatementpstmt=null;
ResultSetrs=null;
Stringquery="";
conn.setAutoCommit(false);
query="insertintoclobtest_table(id,picstr)values(?,empty_clob())";
java.sql.PreparedStatementpstmt=conn.prepareStatement(query);
pstmt.setString(1,"001");
pstmt.executeUpdate();
pstmt=null
query="selectpicstrfromclobtest_tablewhereid='001'forupdate";
pstmt=con.prepareStatement(query)
rs=pstmt.executeQuery();
oracle.sql.CLOBclobtt=null;
if(rs.next()){
clobtt=(oracle.sql.CLOB)rs.getClob(1);
}
Writerwr=clobtt.getCharacterOutputStream();
wr.write(strtmp);
wr.flush();
wr.close();
rs.close();
con.commit();(2)通過sql/plus查詢是否已經成功插入資料庫
*************************************************
PL/SQL的包DBMS_LOB來處理LOB數據。察看剛才的插入是否成功。使用DBMS_LOB包的getlength這個procere來檢測是否已經將str存入到picstr欄位中了。如:
SQL>selectdbms_lob.getlength(picstr)fromclobtest_table;
(3)對資料庫clob型執行讀取操作
*************************************************
讀取相對插入就很簡單了。基本步驟和一半的取資料庫數據沒有太大的差別。
Stringdescription=""
query="selectpicstrfromclobtest_tablewhereid='001'";
pstmt=con.prepareStatement(query);
ResultSetresult=pstmt.executeQuery();
if(result.next()){
oracle.jdbc.driver.OracleResultSetors=
(oracle.jdbc.driver.OracleResultSet)result;
oracle.sql.CLOBclobtmp=(oracle.sql.CLOB)ors.getClob(1);
if(clobtmp==null||clobtmp.length()==0){
System.out.println("======CLOB對象為空");
description="";
}else{
description=clobtmp.getSubString((long)1,(int)clobtmp.length());
System.out.println("======字元串形式"+description);
}
}
2. java中如何將大於10000的字元串,插入oracle資料庫中的blob類型欄位中
不要用blob,用clob類型。先插入一個empty_clob(),然後用Statement myStmt = conn.createStatement();
ResultSet clobResultSet=myStmt.executeQuery("SELECT "+strCLOBColName
+" FROM "+strTable
+" WHERE "+ strIdColName +" ='" + strIdValue+ "' FOR UPDATE ");
CLOB myClob = (oracle.sql.CLOB)clobResultSet.getClob(strCLOBColName);
myClob.putString(1,strBuff);
myStmt.execute("COMMIT");
clobResultSet.close();
myStmt.close();
conn.setAutoCommit(true);
3. oracle資料庫CLOB類型怎麼轉換為String
給你段參考代碼,讀取clob數據
import java.io.InputStream;
import java.io.Reader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class TestClobOut {
public static void main(String args[]){
String data;
Reader inStream=null;
//獲得資料庫連接
Connection con = ConnectionFactory.getConnection();//ConnectionFactory類是另外定義的,不必糾結
con.setAutoCommit(false);
Statement st = con.createStatement();
//不需要「for update」
ResultSet rs = st.executeQuery("select CLOBATTR from TESTCLOB where ID=1");
if (rs.next())
{
java.sql.Clob clob = rs.getClob("CLOBATTR");
inStream = clob.getCharacterStream();
char[] c = new char[(int) clob.length()];
inStream.read(c);
//data是讀出並需要返回的數據,類型是String
data = new String(c);
inStream.close();
}
inStream.close();
con.commit();
con.close();
}
}
4. jndi(java命名與目錄介面)api下有哪些常用的包和介面
JNDI(Java 命名和目錄介面)
分布式計算環境通常使用命名和目錄服務來獲取共享的組件和資源。命名和目錄服務將名稱與位置、服務、信息和資源關聯起來。
命名服務提供名稱—對象的映射。目錄服務提供有關對象的信息,並提供定位這些對象所需的搜索工具。有許多命名和目錄服務實現,並且到它們的介面是不同的。
Java 命名和目錄介面或 JNDI 提供了一個用於訪問不同的命名和目錄服務的公共介面。請參閱 URL java.sun.com/procts/jndi/serviceproviders.html 以獲取支持通過 JNDI 介面訪問命名和目錄服務的供應商列表。
JNDI(Java Naming and Directory Interface)
當你在開發企業beans時,JNDI很重要,因為對一個EJB的訪問是通過JNDI的命名服務完成的。運用一個命名服務來查找與一個特定名字相關的一個對象。在EJB context中,一個命名服務找到一個企業bean,給定這個bean的名字。因此,了解JNDI在開發一個EJB應用程序中是至關重要的。另外,JDBC可以用JNDI來訪問一個關系資料庫。
附:The JNDI Tutorial
http://java.sun.com/procts/jndi/tutorial/index.html
(下載)
http://java.sun.com/procts/jndi/docs.html#TUTORIAL
JDBC2.0擴展API(1)
[ 作者: 不詳 添加時間: 2001-8-24 14:11:50 ]
來源:www.csdn.net
JDBC 2.0 API被劃分為兩部分:JDBC 2.0核心API和JDBC 2.0標准擴展API。核心API在java.sql裡面。這是原來的版本就實現了的基本的功能。標准擴展API在javax.sql裡面。由JDBC2.0規范新規定的一些介面在這裡面。當然,JDBC2.0也對原來版本的java.sql核心做了一些改動。不過不是很大。原來JDBC1.0的程序可以不加修改的在JDBC2.0上運行。這是Java的一貫的良好的作風。最新的JDBC包可以從sun公司的網站上下載。
JDBC2.0的擴展API增加了一些數據訪問和數據源訪問的重大的功能。這中間有一些是主要用來做企業計算的。用JDBC2.0的新的擴展包,JDBC提供了一個從JAVA2平台的通用的數據訪問的方法。
首先,我們來看看JDBC標准擴展的API怎樣來和JDBC2.0結合在一起的。JDBC2.0包括兩個包:
1、 java.sql包,個包裡面是JDBC2.0的核心API。它包括了原來的JDBC API(JDBC 1.0版本),再加上一些新的2.0版本的API。這個包在Java 2 Platform SDK裡面有。
2、 javax.sql包,這裡面是JDBC2.0的標准擴展API。這個包是一個全新的,在Java 2 Platform SDK, Enterprise Edition裡面單獨提供。
JDBC2.0的核心API包括了JDBC1.0的API,並在此基礎上增加了一些功能,對某些性能做了增強。使java語言在資料庫計算的前端提供了統一的數據訪問方法,效率也得到了提高。
JDBC是向後兼容的,JDBC1.0的程序可以不加修改的運行在JDBC2.0上。但是,假如程序中用到了JDBC2.0的新特性,就必須要運行在JDBC2.0版本上。
概括的來說,JDBC核心API的新特性在兩個方面做了工作。一個是支持一些新的功能,另一個就是支持SQL3的數據類型。
1、 在支持新功能方面:包括結果集可以向後滾動,批量的更新數據。另外,還提供了UNICODE字元集的字元流操作。
2、 在支持SQL3的數據類型方面:包括新的SQL3數據類型,增加了對持久性對象的存貯。
為了對數據的存取,操作更加方便,JDBC的新特性是應用程序的設計更容易了。例如:數據塊的操作能夠顯著的提高資料庫訪問的性能。新增加的BLOB, CLOB,和數組介面能夠是應用程序操作大塊的數據類型,而不必客戶端在存貯之前進行其它的處理。這樣,就顯著的提高了內存的使用效率。
下面我們來介紹JDBC2.0的標准擴展API。標准擴展API分為如下幾個方面:
1、 DataSource介面:和Java名字目錄服務(JNDI)一起工作的數據源介面。它提供了對數 吹囊恢指玫牧臃椒ā?br>;2、 Connection pooling(連接池):可以重復使用連接,而不是對每個請求都使用一個新的連接。
3、 Distrubute transaction(分布式的事務):在一個事務中涉及到了多個資料庫伺服器。
4、 Rowsets:JavaBean組件包含了結果集,主要用來將數據傳給瘦客戶,或者提供一個可以滾動的結果集。
下面我們一個一個來介紹:
一、DataSource介面是一個更好的連接數據源的方法:
JDBC1.0是原來是用DriverManager類來產生一個對數據源的連接。JDBC2.0用一種替代的方法,使用DataSource的實現,代碼變的更小巧精緻,也更容易控制。
一個DataSource對象代表了一個真正的數據源。根據DataSource的實現方法,數據源既可以是從關系資料庫,也電子表格,還可以是一個表格形式的文件。當一個DataSource對象注冊到名字服務中,應用程序就可以通過名字服務獲得DataSource對象,並用它來產生一個與DataSource代表的數據源之間的連接。
關於數據源的信息和如何來定位數據源,例如資料庫伺服器的名字,在哪台機器上,埠號等等,都包含在DataSource對象的屬性裡面去了。這樣,對應用程序的設計來說是更方便了,因為並不需要硬性的把驅動的名字寫死到程序裡面去。通常驅動名字中都包含了驅動提供商的名字,而在DriverManager類中通常是這么做的。如果數據源要移植到另一個資料庫驅動中,代碼也很容易做修改。所需要做的修改只是更改DataSource的相關的屬性。而使用DataSource對象的代碼不需要做任何改動。
由系統管理員或者有相應許可權的人來配置DataSource對象。配置DataSource,包括設定DataSource的屬性,然後將它注冊到JNDI名字服務中去。在注冊DataSource對象的的過程中,系統管理員需要把DataSource對象和一個邏輯名字關聯起來。名字可以是任意的,通常取成能代表數據源並且容易記住的名字。在下面的例子中,名字起為:InventoryDB,按照慣例,邏輯名字通常都在jdbc的子上下文中。這樣,邏輯名字的全名就是:jdbc/ InventoryDB。
一旦配置好了數據源對象,應用程序設計者就可以用它來產生一個與數據源的連接。下面的代碼片段示例了如何用JNDI上下文獲得一個一個數據源對象,然後如何用數據源對象產生一個與數據源的連接。開始的兩行用的是JNDI API,第三行用的才是JDBC的API:
Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("jdbc/InventoryDB");Connection con = ds.getConnection("myPassword", "myUserName");
在一個基本的DataSource實現中,DataSource.getConnection方法返回的Connection對象和用DriverManager.getConnection方法返回的Connection對象是一樣的。因為DataSource提供的方便性,我們推薦使用DataSource對象來得到一個Connection對象。我們希望所以的基於JDBC2.0技術的資料庫驅動都包含一個基本的DataSource的實現,這樣就可以在應用程序中很容易的使用它。
對於普通的應用程序設計者,是否使用DataSource對象只是一個選擇問題。但是,對於那些需要用的連接池或者分布式的事務的應用程序設計者來說,就必須使用DataSource對象來獲得Connection,原因在下面我們會提到。
二、Connection pooling(連接池):
連接池是這么一種機制,當應用程序關閉一個Connection的時候,這個連接被回收,而不是被destroy,因為建立一個連接是一個很費資源的操作。如果能把回收的連接重新利用,會減少新創建連接的數目,顯著的提高運行的性能。
假設應用程序需要建立到一個名字為EmpolyeeDB的DataSource的連接。使用連接池得到連接的代碼如下:
Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("jdbc/EmployeeDB");Connection con = ds.getConnection("myPassword", "myUserName");除了邏輯名字以外,我們發現其代碼和上面舉的例子的代碼是一樣的。邏輯名字不同,就可以連接到不同的資料庫。DataSource對象的getConnection方法返回的Connection是否是一個連接池中的連接完全取決於DataSource對象的實現方法。如果DataSource對象實現與一個支持連接池的中間層的伺服器一起工作,DataSource對象就會自動的返回連接池中的連接,這個連接也是可以重復利用的。
是否使用連接池獲得一個連接,在應用程序的代碼上是看不出不同的。在使用這個Connection連接上也沒有什麼不一樣的地方,唯一的不同是在java的finally語句塊中來關閉一個連接。在finally中關閉連接是一個好的編程習慣。這樣,即使方法拋出異常,Connection也會被關閉並回收到連接池中去。代碼應該如下所示:
try{…
}catch(){…
}finally{ if(con!=null)con.close();}
三、分布式事務:
獲得一個用來支持分布式事務的連接與獲得連接池中的連接是很相似的。同樣,不同之處在於DataSource的實現上的不同,而不是在應用程序中獲得連接的方式上有什麼不同。假設DataSource的實現可以與支持分布式事務中間層伺服器一起工作,得到連接的代碼還是如下所示:
Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("jdbc/EmployeeDB"); Connection con = ds.getConnection("myPassword", "myUserName");由於性能上的原因,如果一個DataSource能夠支持分布式的事務,它同樣也可以支持連接池管理。
從應用程序設計者的觀點來看。是否支持分布式的事務的連接對它來說沒什麼不同,唯一的不同是在事務的邊界上(開始一個事務的地方和結束一個事務的地方),開始一個事務或者結束一個事務都是由事務伺服器來控制的。應用程序不應該做任何可能妨礙服務的事情。應用程序不能夠直接調用事務提交commit或者回滾rollback操作,也不能夠使用事務的自動提交模式auto-commit mode(在資料庫操作完成的時候自動的調用commit或者rollback)。
在一個連接參與了分布式事務的時候,下面的代碼是你不能做的(con表示支持分布式事務的連接Connection)。
con.commit();或者con.rollback();或者con.setAutoCommit(true);對於通常的Connection來說,預設的是auto-commit模式。而對於支持分布式事務的Connection來說,預設不是auto-commit模式。注意,即使Connection是支持事務的,它也可以用於沒有事務的情況。關於事務邊界的限制只是是對分布式事務的情況下才成立的。
配置支持連接池的DataSource的時候,涉及到配置ConnectionPoolDataSource對象,這個對象是三層體系結構中的中間層來管理連接池的。同樣的,在配置支持分布式事務的時候,需要配置XADataSource,XADataSource是中間層用來管理分布式事物的對象。ConnectionPoolDataSource和XADataSource是由驅動提供商提供的,對應用程序的設計者來說是透明的。和基本的DataSource一樣,系統管理員來配置ConnectionPoolDataSource和XADataSource對象。
四、結果集:
結果集對象是一行行數據的容器。根據其目的,可以通過多種方法實現。RowSet及其相關的介面與JDBC2.0的標准擴展API有點不同,他們並不是驅動的一部分,RowSet是在驅動的上層實現的,可以由其它的任何人來實現他們。
任何類型的rowset都實現了RowSet介面,RowSet介面擴展了ResultSet介面。這樣RowSet對象就有了ResultSet對象所有的功能。能夠通過getXXX方法得到資料庫中的某列值,通過updateXXX方法可以修改某列值,可以移動游標,是當前行變為另一行。
當然,我們更感興趣的是RowSet介面提供的新的功能。作為一個JavaBean組件,RowSet對象可以增加或者刪除一個listener(監聽者),可以get或者set其屬性值,這些屬性中,有一個是字元串,表示一個對資料庫Query請求,RowSet介面定義了設定參數的方法,也提供了執行這個請求的方法。這意味著RowSet對象能夠執行查詢請求,可以根據它產生的結果集進行計算。同樣,RowSet也可以根據任何錶格數據源進行計算,所以,它不局限於關系資料庫。
從數據源得到數據之後,RowSet對象可以和數據源斷開連接,rowset也可以被序列化。這樣,RowSet就可以通過網路傳遞給瘦客戶端。
RowSet可以被重新連接到數據源,這樣,做的修改就可以存回到數據源中去。如果產生了一個listener,當RowSet的當前行移動,或者數據被修改的時候,監聽者就會收到通知。例如,圖形用戶界面組件可以注冊成為監聽者,當RowSet更改的時候,圖形用戶界面接到通知,就可以修改界面,來符合它所表示的RowSet。
根據不同的需要,RowSet介面可以通過多種方法來實現。Java software已經寫了一個CachedRowSet實現,從http://developer.java.sun.com/developer/earlyAccess/crs/index.html中可以得到這個實現。
與CachedRowSet類不樣的是,JDBCRowSet類總是保持一個和數據源的連接。這樣,在ResultSet外圍簡單到加了一層,是基於JDBC技術的驅動看起來象是一個簡單的JavaBean組件一樣。
總結:JDBC2.0標准擴展API通過見DataSource注冊到JNDI名字服務上,將JDBC技術擴展為一個全新的概念。使應用程序的代碼更加精巧,易於控制。新的API支持了連接池,支持分布式的事務。最後,還使java應用程序可以在網路上傳播結果集,是不可以滾動的ResultSet變成了可以滾動的RowSet。
5. java如何把在線編輯器的內容存儲到資料庫
<FCK:editor instanceName="設定的屬性" height="400" width="100%" toolbarSet="Text" basePath="/static/FCKeditor/"> </FCK:editor>
在進入action後,接收,保存即可
另外就是一般使用fck搭配的是資料庫中的內clob欄位
在存儲的時候使用下容面的語句:
sql = "select content from 資料庫名稱 for update";
rs = DbQuery(sql);
rs.getClob("CLOB");
OracleThinClob clobComment = null;
if (rs.next()) {
clobComment = (OracleThinClob) rs.getClob("content");
}
Writer w = clobComment.getCharacterOutputStream();
w.write(用於接收內容的屬性);
w.flush();
w.close();