Hibernate深入浅出(十五)-----读深入浅出hibernate有感
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();
}
}
}
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、表与类的一对多关系