日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Java大對(duì)象類型的Hibernate映射

 feimishiwo 2014-04-29
  
Java中,java.lang.String可用于表示長(zhǎng)字符串(長(zhǎng)度超過255),字節(jié)數(shù)組byte[]可以用于存放圖片戶或文件二進(jìn)制數(shù)據(jù)。此外,在JDBC API中還提供了java.sql.CLOBjava.sql.BLOB類型,他們分別表示標(biāo)準(zhǔn)SQL中的CLOB(字符大對(duì)象)和BLOB(二進(jìn)制大對(duì)象)類型。表2.4列出了Java大對(duì)象,Hibernate映射類型以及標(biāo)準(zhǔn)SQL的對(duì)應(yīng)關(guān)系。
2.4
 
 
 
 
映射類型
Java類型
標(biāo)準(zhǔn)SQL類型
binary
byte[]
VARBINARY(或者BLOB)
text
java.lang.String
CLOB
serilizable
實(shí)現(xiàn)java.io.Serializable的任何一個(gè)Java
VARBINARY(或者BLOB)
clob
java.sql.CLOB
CLOB
blob
java.sql.BLOB
BLOB
注意:不允許用表2.4中列出的數(shù)據(jù)類型來(lái)定義持久化類的OID
2)、BLOB,CLOB數(shù)據(jù)的處理(以Oracle數(shù)據(jù)庫(kù)為例):
 假設(shè)我們有如下表
 
T_User 
id     number   <pk>
name varchar2(50)
age    number
image    BLOB
resume   CLOB          
 對(duì)應(yīng)的映射文件如下:
<hibernate-mapping>
 <class name=”com.neusoft.hibernate.db.entity.TUser” table=”T_User”>
<id name=”id” column=”id” type=”java.lang.Integer”>
 <generator class=”native”/>
</id>
<property name=”name” type=”java.lang.String” column=”name”/>
<property name=”age” type=”java.lang.Integer” column=”age”/>
<property name=”image” type=”java.sql.Blob” column=”image”/>
<property name=”resume” type=”java.sql.Clob” column=”resume”/>
 </class>
</hibernate-mapping>
實(shí)體類如下:
public class Tuser implements Serializable{
 private Integer id;
 private String name;
 private Integer age;
 private Blob image;
 private Clob resume;
 …getter/setter…..
}
對(duì)BLOBCLOB這種大對(duì)象一般都是采用流機(jī)制作為數(shù)據(jù)讀取方式,所以這種讀取方式在Oracle這種自視為數(shù)據(jù)庫(kù)中貴族的數(shù)據(jù)庫(kù)中對(duì)這種操作就會(huì)有諸多的限制,有時(shí)候會(huì)叫人覺得不太友好(這是典型的店大欺客)
限制一:Oracle JDBC不允許流操作以批量方式執(zhí)行,如果發(fā)生這種錯(cuò)誤一般會(huì)拋出
ERROR JDBCExceptionReport:streams type cannot be used in batching.出現(xiàn)這種情況一般都需要將hibernate.cfg.xml中的hibernate.jdbc.batch_size設(shè)定為0即可消除,但是這就會(huì)影響其他的更新,插入,刪除操作的性能,因此必須在一個(gè)數(shù)據(jù)庫(kù)事務(wù)中對(duì)Clob,Blob進(jìn)行操作,也只有在一個(gè)數(shù)據(jù)庫(kù)事務(wù)中Clob,Blob對(duì)象才會(huì)有效。
限制二:Oalce Blob/Clob具有獨(dú)特的訪問方式,這種類型字段擁有一個(gè)游標(biāo)(cursor),JDBC必須通過游標(biāo)對(duì)Blob/Clob進(jìn)行操作,在Blob/Clob創(chuàng)建之前我門無(wú)法獲得其游標(biāo)句炳,這就意味著必須首先創(chuàng)建一個(gè)空Blob/Clob字段,在叢空Blob/Clob獲取游標(biāo),然后寫入我們期望的數(shù)據(jù)。
 
首先看一下采用傳統(tǒng)JDBC進(jìn)行操作的代碼:
//….獲取Connection連接
conn.setAtuoCommit(false);
//插入Blob/Clob空值字段
PrepareStatement prestmt=conn.prepareStatement(“insert into T_USER(name,age,id,image,resume) values(?,?,?,?,?)”);
prestmt.setString(1,”zx”);
prestmt.setInt(2,26);
prestmt.setInt(3,5);
//通過oracle.sql.BLOB/CLOB.empty_lob()方法構(gòu)造空Blob/Clob對(duì)象
prestmt.setBlob(4,oracle.sql.BLOB.empty_lob());
prestmt.setClob(5,oracle.sql.CLOB.empty_lob());
prestmt.executeUpdate();
prestmt.close();
//再次從數(shù)據(jù)庫(kù)中獲得Blob/Clob句炳
prestmt=conn.prepareStatement(“select image,resume from T_USER where id=? for update ”);
prestmt.setInt(1,5);
ResultSet rset=prestmt.executeQuery();
rset.next();
oracle.sql.BLOB imgBlob=(oracle.sql.BLOB)rset.getBlob();
oracle.sql.CLOB resClob=(oracle.sql.CLOB)rset.getClob();
//將二進(jìn)制數(shù)據(jù)寫入Blob
FlieInputStream fin=new FileInputStream(“c://image.jpg”);
OutputStream out=imgBlob.getBinaryOutputStream();
byte[] buf=new byte[fin.available()];
int len;
while((len=fin.read(buf))!=-1){
 out.write(buf,0,len);
}
fin.close();
out.close();
//將字符串寫入Clob
resClob.putString(1,”This is my clob”);
//將更新寫回?cái)?shù)據(jù)庫(kù)
prestmt=conn.prepareStatement(“update T_USER set image=?,resume=? where id=? ”);
prestmt.setBlob(1,imgBlob);
prestmt.setClob(2,resClob);
prestmt.setInt(3,5);
prestmt.executeUpdate();
prestmt.close();
conn.commit();
conn.close();
 
 
以上是傳統(tǒng)的采用JDBC方式處理,注意他將連接的自動(dòng)提交屬性設(shè)置為false然后將所有的操作并入一個(gè)事務(wù)中,然后進(jìn)行提交,這是處理OracleBlob/Clob字段的一般機(jī)制,所以Hibernate的處理就應(yīng)該模仿JDBC的處理方式,因?yàn)閺哪撤N角度來(lái)講Hibernate是對(duì)JDBC的封裝因?yàn)樗牡讓釉L問機(jī)制仍然是基于JDBC的。
 
Hibernate的處理:
TUser user=new TUser();
user.setAge(new Integer(26));
user.setName(“zx”);
//創(chuàng)建空Blob/Clob對(duì)象
user.setImage(Hibernate.createBlob(new byte[1]));
user.setResume(Hibernate.createClob(“ “));//注意這里的參數(shù)是一個(gè)空格
Transaction tx=session.beginTransaction();
session.save(user);
//調(diào)用flush方法,強(qiáng)制Hibernate立即執(zhí)行insert sql
session.flush();
//通過refresh方法,強(qiáng)制Hibernate執(zhí)行select for update
session.refresh(user,LockMode.UPGRADE);
//Blob寫入實(shí)際內(nèi)容
oracle.sql.BLOB blob=(oracle.sql.BLOB)user.getImger();
OutputStream out=blob.getBinaryOutputStream();
FileInputStream fin=new FileInputStream(“c://image.jpg”);
byte[] buf=new byte[fin.available()];
int len;
while((len=fin.read())!=-1){
 out.write(buf,0,len);
}
fin.close();
out.close();
//Clob中寫入數(shù)據(jù)
oracle.sql.CLOB clob=user.getResume();
java.io.Writer writer=clob.getCharacterOutputStream();
writer.write(“This is my resume!”);
writer.close();
session.saveOrUpdate(user);
session.commit();
tx.commit();
 
在實(shí)際應(yīng)用中,對(duì)于Clob字段可以簡(jiǎn)單的將其映射為String類型,不過在Oracle Thin Driver對(duì)Clob字段支持上有欠缺,當(dāng)Clob內(nèi)容超過4000字節(jié)時(shí)將無(wú)法讀取,而Oracle OCI Driver(需要在本地安裝客戶端組件)則可以完成大容量Clob字段操作。
 
對(duì)于上面的代碼相信作為成熟的工程師來(lái)說都聞到一些bad smell,如果Blob/Clob字段普遍存在的話,那么我們的持久層邏輯可能遍布這種復(fù)雜的邏輯,不過不要著急在我即將講解的客戶自定義類中我們將會(huì)看到一個(gè)解決方案,通過自定義類型我們可以對(duì)數(shù)據(jù)類型的通用性進(jìn)行抽象,對(duì)于Blob/Clob字段我們可以定義一種類型并以這種類型作為Blob/Clob字段的映射類型。(好了等到下一篇再說吧!)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多