Blob、Clob字段的映射
Blob和Clob字段的區別在于,Blob字段采用單字節存儲,適合保存二進制數據,如圖片文件。Clob字段采用多字節存儲,適合保存大型文本數據。
在Oracle中Blob/Clob字段獨特的訪問方式,Oracle Blob/Clob字段本身擁有一個游標,JDBC必須必須通過游標對Blob/Clob字段進行操作,在Blob/Clob字段被創建之前,我們無法獲取其游標句柄,這也意味著,我們必須首先創建一個空Blob/Clob字段,再從這個空Blob/Clob字段獲取游標,寫入我們所期望保存的數據。
實體粒度設計:
在Hibernate世界里,我們經常聽到"fine-grained object model"直接翻譯就是適當的細粒度對象模型。
適當的比較模糊,細粒度就是將原本業務模型中的對象加以細分,從而得到更加精細的對象模型。就是劃分出更多的對象。分為:面向設計的細粒度劃分和面向性能的細粒度劃分。
對于單表的對象細分,在Hibernate中可借助Component節點的定義來完成。何謂Component?從名字上來看,既然稱之為組件,則其必然是從屬于某個整體的一個組成部分。在Hibernate語義中,我們將某個實體對象中的一個邏輯組成成為Component.Component與實體對象的根本差別,就在于Component沒有標示,它作為一個邏輯組成,完全從屬于實體對象。通過Component定義,我們將T_User表實際映射到了3個類,TUser,Contact和Name,這樣我們就可以在傳統關系型庫表上,實現了面向對象的領域劃分。
面向性能的細粒度劃分:
當我們通過Hibernate加載TUser對象時,Hibernate會從庫表中讀取所有的字段數據,并構造TUser實例返回。這里就產生了一個性能方面的問題,作為blob/clob等重量級字段類型,數據庫讀取操作代價較高。對于需要處理resume和image的應用邏輯而言,這樣的代價無法避免,而對于那些無需resume和image信息的操作而言,如此性能無謂的損耗實在可惜。
如何避免這個問題,Hibernate3提供了屬性的延遲加載功能,通過這個功能,我們可以在調用TUser.getResume/getImage時才真正從數據庫中讀取數據。對于hibernate2來說我們通過繼承關系,我們將一個對象進行縱向細分來解決這個問題。我們通過在子類的映射文件中class節點指定polymorphism="explicit"聲明了一個顯示多態關系。聲明為顯示多態的類,只有在明確指定類名的時候才會返回此類實例。
package com.wyq.hibernateLoad;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.SQLException;
import org.hibernate.Hibernate;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.wyq.hibernate.TUser2;
public class TUserOperator {
Session session = null;
//復合主鍵加載數據
public void loadData(){
TUser2 user = new TUser2();
user.setFirstname("Kevin");
user.setLastname("Shark");
user = (TUser2)session.load(TUser2.class, user);
System.out.println("User age is=>"+user.getAge());
}
//SQL保存圖片
public void saveImage(){
TUser2 user = new TUser2();
user.setAge(new Integer(20));
try {
FileInputStream imgis = new FileInputStream("C:\\inimage.jpg");
Blob img = Hibernate.createBlob(imgis);
user.setImage(img);
Clob resume = Hibernate.createClob("This is Clob");
user.setResume(resume);
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//SQL讀取圖片
public void getImageObj(){
TUser2 user = (TUser2)session.load(TUser2.class,new Integer(3));
Clob resume = user.getResume();
Blob img = user.getImage();
try {
InputStream is = img.getBinaryStream();
FileOutputStream fos = new FileOutputStream("c:\\outimage.jpg");
byte[] buf = new byte[102400];
int len;
while((len=is.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
is.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//Oracle保存圖片
public void saveForOracleImage(){
TUser2 user = new TUser2();
user.setAge(new Integer(20));
user.setImage(Hibernate.createBlob(new byte[1]));
user.setResume(Hibernate.createClob(" "));//注意這里的參數是一個空格
Transaction tx = session.beginTransaction();
session.save(user);
//調用flush方法,強制Hibernate立即執行insert sql
session.flush();
//通過refresh方法,強制Hibernate執行select for update
session.refresh(user, LockMode.UPGRADE);
//向Blob寫入實際內容
oracle.sql.BLOB blob = (oracle.sql.BLOB)user.getImage();
try {
OutputStream out = blob.getBinaryOutputStream();
FileInputStream imgis = new FileInputStream("c:\\inimage.jpg");
byte[] buf = new byte[10240];//10k緩存
int len;
while((len=imgis.read(buf))>0){
out.write(buf,0,len);
}
imgis.close();
out.close();
//向CLOB寫入實際內容
oracle.sql.CLOB clob = (oracle.sql.CLOB)user.getResume();
java.io.Writer writer = clob.getCharacterOutputStream();
writer.write("this is my resume");
writer.close();
session.save(user);
tx.commit();
} catch (SQLException e) {
e.printStackTrace();
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
實體層次設計:繼承關系是關系型數據與面向對象數據結構之間的主要差異之一。
Hibernate中支持3種類型的繼承形式:
1、表與子類之間的獨立一對一關系。
2、每個子類對應一張子表,并與主類共享主表
3、表與類的一對多關系
posted on 2009-10-27 22:32
王永慶 閱讀(227)
評論(0) 編輯 收藏 所屬分類:
HIBERNATE