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
王永庆 阅读(216)
评论(0) 编辑 收藏 所属分类:
HIBERNATE