java clob是什么,讓我們一起了解一下?
創(chuàng)新互聯(lián)基于成都重慶香港及美國(guó)等地區(qū)分布式IDC機(jī)房數(shù)據(jù)中心構(gòu)建的電信大帶寬,聯(lián)通大帶寬,移動(dòng)大帶寬,多線BGP大帶寬租用,是為眾多客戶提供專業(yè)移動(dòng)服務(wù)器托管報(bào)價(jià),主機(jī)托管價(jià)格性價(jià)比高,為金融證券行業(yè)服務(wù)器托管,ai人工智能服務(wù)器托管提供bgp線路100M獨(dú)享,G口帶寬及機(jī)柜租用的專業(yè)成都idc公司。
CLOB是內(nèi)置類型,將字符大對(duì)象存儲(chǔ)為數(shù)據(jù)庫(kù)表某一行中的一個(gè)列值。默認(rèn)情況下,驅(qū)動(dòng)程序使用SQL locator實(shí)現(xiàn)Clob對(duì)象,這意味著CLOB對(duì)象包含一個(gè)指向SQL CLOB數(shù)據(jù)的邏輯指針而不是數(shù)據(jù)本身。
在JAVA如何使用CLOB進(jìn)行操作?
在絕大多數(shù)情況下,有2種方法使用CLOB。
1、相對(duì)比較小的,可以用String進(jìn)行直接操作,把CLOB看成字符串類型即可。
2、如果比較大,可以用 getAsciiStream 或者 getUnicodeStream 以及對(duì)應(yīng)的 setAsciiStream 和 setUnicodeStream 即可。
(1)讀取數(shù)據(jù):
ResultSet?rs?=?stmt.executeQuery("SELECT?TOP?1?*?FROM?Test1"); rs.next(); Reader?reader?=?rs.getCharacterStream(2);
(2)插入數(shù)據(jù):
PreparedStatement?pstmt?=?con.prepareStatement("INSERT?INTO?test1?(c1_id,?c2_vcmax)?VALUES?(?,??)"); pstmt.setInt(1,?1); pstmt.setString(2,?htmlStr); pstmt.executeUpdate();
(3)更新數(shù)據(jù):
Statement?stmt?=?con.createStatement(); ResultSet?rs?=?stmt.executeQuery("SELECT?*?FROM?test1"); rs.next(); Clob?clob?=?rs.getClob(2); long?pos?=?clob.position("dog",?1); clob.setString(1,?"cat",?len,?3); rs.updateClob(2,?clob); rs.updateRow();
那么java是如何操作數(shù)據(jù)庫(kù)clob字段的?
示例代碼如下: package?com.test.db.clob; import?java.io.BufferedReader; import?java.io.IOException; import?java.io.Writer; import?java.sql.Clob; import?java.sql.Connection; import?java.sql.DriverManager; import?java.sql.PreparedStatement; import?java.sql.ResultSet; import?java.sql.SQLException; import?java.sql.Statement; public?class?ClobTest?{undefined private?static?Connection?conn; static?{undefined try?{undefined Class.forName("oracle.jdbc.driver.OracleDriver"); conn?=?DriverManager.getConnection( "jdbc:oracle:thin:@localhost:1521:orcl","scott","tiger"); }?catch?(ClassNotFoundException?e)?{undefined e.printStackTrace(); }?catch?(SQLException?e)?{undefined e.printStackTrace(); } } public?static?void?main(String[]?args)?throws?SQLException,?IOException?{undefined testInsert(); testUpdate(); testRead(); } private?static?void?testInsert()?throws?SQLException?{undefined String?sql?=?"insert?into?test_clob?values(1,?empty_clob())"; Statement?stm?=?conn.createStatement(); stm.execute(sql); } private?static?void?testUpdate()?throws?SQLException,?IOException?{undefined String?sql?=?"select?content?from?test_clob?where?id?=?1?for?update"; Statement?stm?=?conn.createStatement(); ResultSet?rs?=?stm.executeQuery(sql); while?(rs.next())?{undefined Clob?c?=?rs.getClob(1); c.truncate(0);//?clear Writer?w?=?c.setCharacterStream(1);//The?first?position?is?1 w.write("abc"); w.close(); c.setString(c.length()?+?1,?"abc"); conn.commit(); } } private?static?void?testRead()?throws?SQLException,?IOException?{undefined String?sql?=?"select?content?from?test_clob?where?id?=?1"; PreparedStatement?pstm?=?conn.prepareStatement(sql); ResultSet?rs?=?pstm.executeQuery(); while?(rs.next())?{undefined Clob?clob?=?rs.getClob("content"); System.out.println("clob.getSubString(1,?2)?--?"?+?clob.getSubString(1,?2)); System.out.println("clob.getSubString(1,?(int)clob.length())?--?"?+ clob.getSubString(1,?(int)clob.length())); BufferedReader?r?=?new?BufferedReader(clob.getCharacterStream()); String?s; while?((s?=?r.readLine())?!=?null)?{undefined System.out.println(s); } r.close(); } } }
1.使用jdk中的方法進(jìn)行傳輸。在ResultSet 中有g(shù)etBlob()方法,在PreparedStatement中有setBlob()方法,所以大多數(shù)人都會(huì)嘗試setBlob
(),getBlob() 進(jìn)行讀寫,或者兩個(gè)數(shù)據(jù)庫(kù)之間BLOB的傳輸。這種方法實(shí)際上是行不通的,據(jù)網(wǎng)上的一些資料介紹,說(shuō)sun官方的文檔有些方法
都是錯(cuò)誤的。
2.使用ResultSet.getBinaryStream 和PreparedStatement.setBinaryStream對(duì)BLOB進(jìn)行讀寫或兩個(gè)數(shù)據(jù)庫(kù)間的傳輸。這種方法我自己嘗試過(guò),
發(fā)現(xiàn),如果BLOB中存儲(chǔ)的是文本文件的話,就沒(méi)問(wèn)題,如果是二進(jìn)制文件,傳輸就會(huì)有問(wèn)題。
根據(jù)自己的經(jīng)驗(yàn),以及查閱了Oracle的官方文檔,都是使用如下處理方法:
1.新建記錄,插入BLOB數(shù)據(jù)
1.1首先新建記錄的時(shí)候,使用oracle的函數(shù)插入一個(gè)空的BLOB,假設(shè)字段A是BLOB類型的:
insert xxxtable(A,B,C) values(empty_blob(),'xxx','yyyy')
1.2后面再查詢剛才插入的記錄,然后更新BLOB,在查詢前,注意設(shè)置Connection的一個(gè)屬性:
conn.setAutoCommit(false);如果缺少這一步,可能導(dǎo)致fetch out of sequence等異常.
1.3 查詢剛才插入的記錄,后面要加“ for update ”,如下:
select A from xxxtable where xxx=999 for update ,如果缺少for update,可能出現(xiàn)row containing the LOB value is not locked
的異常
1.4 從查詢到的 BLOB字段中,獲取blob并進(jìn)行更新,代碼如下:
BLOB blob = (BLOB) rs.getBlob("A");
OutputStream os = blob.getBinaryOutputStream();
BufferedOutputStream output = new BufferedOutputStream(os);
后面再使用output.write方法將需要寫入的內(nèi)容寫到output中就可以了。例如我們將一個(gè)文件寫入這個(gè)字段中:
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上面執(zhí)行完畢后,記得關(guān)閉output,input,以及關(guān)閉查詢到的ResultSet
1.6最后執(zhí)行conn.commit();將更新的內(nèi)容提交,以及執(zhí)行conn.setAutoCommit(true); 改回Connction的屬性
2.修改記錄,方法與上面的方法類似,
2.1首先更新BLOB以外的其他字段
2.2 使用1.3中類似的方法獲取記錄
2.3 修改的過(guò)程中,注意以下:a 需要更新的記錄中,BLOB有可能為NULL,這樣在執(zhí)行blob.getBinaryOutputStream()獲取的值可能為
null,那么就關(guān)閉剛才select的記錄,再執(zhí)行一次update xxxtable set A = empty_blob() where xxx, 這樣就先寫入了一個(gè)空的BLOB(不是null),然后再
使用1.3,1.4中的方法執(zhí)行更新記錄.b 注意別忘了先執(zhí)行setAutoCommit(false),以及"for update",以及后面的conn.commit();等。
3.讀取BLOB字段中的數(shù)據(jù).
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))) {
//在這里執(zhí)行寫入,如寫入到文件的BufferedOutputStream里
System.out.println(bytesRead);
}
通過(guò)循環(huán)取出blob中的數(shù)據(jù),寫到buff里,再將buff的內(nèi)容寫入到需要的地方
4.兩個(gè)數(shù)據(jù)庫(kù)間blob字段的傳輸
類似上面1和3的方法,一邊獲取BufferedOutputStream,另外一邊獲取BufferedInputStream,然后讀出寫入,需要注意的是寫入所用的
Connection要執(zhí)行conn.setAutoCommit(false);以及獲取記錄時(shí)添加“ for update ”以及最后的commit();
總結(jié)以上方法,其根本就是先創(chuàng)建空的BLOB,再獲取其BufferedOutputStream進(jìn)行寫入,或獲取BufferedInputStream進(jìn)行讀取
(1)對(duì)數(shù)據(jù)庫(kù)clob型執(zhí)行插入操作?
*************************************************?
java.sql.PreparedStatement?pstmt?=?null;?
ResultSet?rs?=?null;?
String?query?=?"";?
conn.setAutoCommit(false);?
query?=?"insert?into?clobtest_table(id,picstr)?values(?,empty_clob())";?
java.sql.PreparedStatement?pstmt?=?conn.prepareStatement(query);?
pstmt.setString(1,"001");?
pstmt.executeUpdate();?
pstmt?=?null?
query?=?"select?picstr?from?clobtest_table?where?id?=?'001'?for?update";?
pstmt?=?con.prepareStatement(query)?
rs=?pstmt.executeQuery();?
oracle.sql.CLOB?clobtt?=?null;?
if(rs.next()){?
clobtt?=?(oracle.sql.CLOB)rs.getClob(1);?
}?
Writer?wr?=?clobtt.getCharacterOutputStream();?
wr.write(strtmp);?
wr.flush();?
wr.close();?
rs.close();?
con.commit();?
(2)通過(guò)sql/plus查詢是否已經(jīng)成功插入數(shù)據(jù)庫(kù)?
*************************************************?
PL/SQL的包DBMS_LOB來(lái)處理LOB數(shù)據(jù)。察看剛才的插入是否成功。使用DBMS_LOB包的getlength這個(gè)procedure來(lái)檢測(cè)是否已經(jīng)將str存入到picstr字段中了。如:?
SQL?select?dbms_lob.getlength(picstr)?from?clobtest_table;?
(3)對(duì)數(shù)據(jù)庫(kù)clob型執(zhí)行讀取操作?
*************************************************?
讀取相對(duì)插入就很簡(jiǎn)單了?;静襟E和一半的取數(shù)據(jù)庫(kù)數(shù)據(jù)沒(méi)有太大的差別。?
String?description?=?""?
query?=?"select?picstr?from?clobtest_table?where?id?=?'001'";?
pstmt?=?con.prepareStatement(query);?
ResultSet?result?=?pstmt.executeQuery();?
if(result.next()){?
oracle.jdbc.driver.OracleResultSet?ors?=?
(oracle.jdbc.driver.OracleResultSet)result;?
oracle.sql.CLOB?clobtmp?=?(oracle.sql.CLOB)?ors.getClob(1);?
if(clobtmp==null?||?clobtmp.length()==0){?
System.out.println("======CLOB對(duì)象為空?");?
description?=?"";?
}else{?
description=clobtmp.getSubString((long)1,(int)clobtmp.length());?
System.out.println("======字符串形式?"+description);?
}?
}
參考:
/**
* 寫入、更新CLOB字段的代碼示例
*/
public void writeClob() {
//自定義的數(shù)據(jù)庫(kù)連接管理類
Connection conn = DbManager.getInstance().getConnection();
try {
conn.setAutoCommit(false);
// 1.這種方法寫入CLOB字段可以。
PreparedStatement stat = conn
.prepareStatement("insert into t_clob (id,clobfield) values(sys_guid(),?)");
String clobContent = "This is a very very long string";
StringReader reader = new StringReader(clobContent);
stat.setCharacterStream(1, reader, clobContent.length());
stat.executeUpdate();
// 2.使用類似的方法進(jìn)行更新CLOB字段,則不能成功
// stat.close();
// stat =null;
// stat =
// conn.prepareStatement("update t_clob set clobfield=? where id=1");
// stat.setCharacterStream(1, reader, clobContent.length());
// stat.executeUpdate();
// 3.需要使用for update方法來(lái)進(jìn)行更新,
// 但是,特別需要注意,如果原來(lái)CLOB字段有值,需要使用empty_clob()將其清空。
// 如果原來(lái)是null,也不能更新,必須是empty_clob()返回的結(jié)果。
stat = conn
.prepareStatement("select clobfield from t_clob where id='1' for update");
ResultSet rs = stat.executeQuery();
if (rs.next()) {
oracle.sql.CLOB clob = (oracle.sql.CLOB) rs
.getClob("clobfield");
Writer outStream = clob.getCharacterOutputStream();
char[] c = clobContent.toCharArray();
outStream.write(c, 0, c.length);
outStream.flush();
outStream.close();
}
conn.commit();
} catch (SQLException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DbManager.getInstance().closeConnection(conn);
}
1:首先:寫個(gè)連接數(shù)據(jù)庫(kù)的類,里面有返回mysq, oracle連接的方法
public Connection getConn(String flag){
Connection con=null;
try
{
if(flag.equals("1"))
{
Class.forName(“oracle.jdbc.driver.OracleDriver”);
con = DriverManager.getConnection(“jdbc:oracle:thin:@IP:1521:數(shù)據(jù)庫(kù)名字”,"name","password");
}
if(flag.equals("2"))
{
Class.forName("org.gjt.mm.mysql.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost/數(shù)據(jù)庫(kù)名?user=用戶名password=密碼useUnicode=truecharacterEncoding=GBK");
}
}
catch(Exception e)
{
e.printStackTrace();
}
return con;
}
2:執(zhí)行插入操作
public void setData() {
conn = new Conn();
try {
String sqlfrom = "select p.id,p.content from table p order by p.id ";
String sqlinsert = "insert into table values(?,?)";
con = conn.getConn("2");
stmt = con.createStatement(); //從mysql取出大字段
rs = stmt.executeQuery(sqlfrom);
con = conn.getConn("1");
PreparedStatement pstmt = con.prepareStatement(sqlinsert); //向oracle中插入大字段
int i = 0;
while (rs.next()) {
pstmt.setInt(1, rs.getInt(1));
pstmt.setClob(2, oracle.sql.CLOB.empty_lob());
pstmt.executeUpdate(); //插入時(shí)將大字段設(shè)為空
this.updateOne(con,rs.getInt(1),rs.getString(2)); // 這里調(diào)用然后更新這個(gè)大字段
}
rs.close(); //關(guān)閉相關(guān)連接
pstmt.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
try
{
con.rollback();
} catch (Exception e1) {
System.out.println("回滾出現(xiàn)異常!");
e1.printStackTrace();
}
}
}
3:該方法實(shí)現(xiàn)對(duì)應(yīng)大字段記錄的更新
public void updateOne(Connection con,int id, String content) {
String str = "select t.content from table t where t.id=" + id+ " for update";
try {
// 注意:存取操作開始前,必須用setAutoCommit(false)取消自動(dòng)提交,否則Oracle將拋出“讀取違反順序”的錯(cuò)誤。
con.setAutoCommit(false);
stmt = con.createStatement();
ResultSet rs_clob = stmt.executeQuery(str);
while ( rs_clob .next()) {
/* 取出clob數(shù)據(jù)*/
oracle.sql.CLOB clob = (oracle.sql.CLOB) rs_clob .getClob(1);
/* 向clob中寫入數(shù)據(jù)*/
clob.putString(1, content);
}
stmt.close();
con.commit();
con.setAutoCommit(true);
con.close();
} catch (Exception e) {
e.printStackTrace();
try
{
con.rollback();
} catch (Exception e1) {
System.out.println("回滾出現(xiàn)異常!");
e1.printStackTrace();
}
}
}
現(xiàn)在就完成了一行記錄的更新。
4:讀clob字段以String 的形式返回(當(dāng)然也可以將讀到的內(nèi)容寫入文件,大家改一下就可以了)
/**
* 讀clob字段
* @param con
* @param id
* @return
*/
public String readClob(Connection con,int id)
{
String content="";
try
{
con.setAutoCommit(false);
stmt=con.createStatement();
ResultSet rs_clob=stmt.executeQuery("select t.content from table t where t.id="+id);
oracle.sql.CLOB contents=null;
while (rs_clob.next())
{ // 取出CLOB對(duì)象
contents= (oracle.sql.CLOB) rs_clob.getClob(1);
}
BufferedReader a = new BufferedReader(contents.getCharacterStream()); //以字符流的方式讀入BufferedReader
String str = "";
while ((str = a.readLine()) != null) {
content = content.concat(str); //最后以String的形式得到
}
con.commit();
/*
BufferedWriter out = new BufferedWriter(new FileWriter("e:/test.txt"));
out.write(content); //寫入文件
out.close(); */
con.setAutoCommit(true);
con.close();
}catch(Exception e)
{
System.out.println("出現(xiàn)異常");
e.printStackTrace();
try
{
con.rollback();
}
catch (Exception e1)
{
System.out.println("回滾出現(xiàn)異常!");
e1.printStackTrace();
}
}
return content;
}
新聞名稱:java代碼插入clob java clob
鏈接URL:http://muchs.cn/article44/ddcijhe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、、品牌網(wǎng)站設(shè)計(jì)、App開發(fā)、自適應(yīng)網(wǎng)站、響應(yīng)式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)