博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java大对象类型的Hibernate映射
阅读量:5941 次
发布时间:2019-06-19

本文共 4651 字,大约阅读时间需要 15 分钟。

hot3.png

Java
中,
java.lang.String
可用于表示长字符串(长度超过
255
),字节数组
byte[]
可以用于存放图片户或文件二进制数据。此外,在
JDBC API
中还提供了
java.sql.CLOB
java.sql.BLOB
类型,他们分别表示标准
SQL
中的
CLOB
(字符大对象)和
BLOB
(二进制大对象)类型。表
2.4
列出了
Java
大对象,
Hibernate
映射类型以及标准
SQL
的对应关系。
2.4
 
 
 
 
映射类型
Java
类型
标准
SQL
类型
binary
byte[]
VARBINARY(
或者
BLOB)
text
java.lang.String
CLOB
serilizable
实现
java.io.Serializable
的任何一个
Java
VARBINARY(
或者
BLOB)
clob
java.sql.CLOB
CLOB
blob
java.sql.BLOB
BLOB
注意:不允许用表
2.4
中列出的数据类型来定义持久化类的
OID
2
)、
BLOB,CLOB
数据的处理(以
Oracle
数据库为例):
 
假设我们有如下表
 
T_User 
id     number   <pk>
name varchar2(50)
age    number
image    BLOB
resume   CLOB          
 
对应的映射文件如下:
<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>
实体类如下:
public class Tuser implements Serializable{
 private Integer id;
 private String name;
 private Integer age;
 private Blob image;
 private Clob resume;
 …getter/setter…..
}
BLOB
CLOB
这种大对象一般都是采用流机制作为数据读取方式,所以这种读取方式在
Oracle
这种自视为数据库中贵族的数据库中对这种操作就会有诸多的限制,有时候会叫人觉得不太友好(这是典型的店大欺客)
限制一:
Oracle JDBC
不允许流操作以批量方式执行,如果发生这种错误一般会抛出
ERROR JDBCExceptionReport:streams type cannot be used in batching.
出现这种情况一般都需要将
hibernate.cfg.xml
中的
hibernate.jdbc.batch_size
设定为
0
即可消除,但是这就会影响其他的更新,插入,删除操作的性能,因此必须在一个数据库事务中对
Clob,Blob
进行操作,也只有在一个数据库事务中
Clob,Blob
对象才会有效。
限制二:
Oalce Blob/Clob
具有独特的访问方式,这种类型字段拥有一个游标
(cursor)
JDBC
必须通过游标对
Blob/Clob
进行操作,在
Blob/Clob
创建之前我门无法获得其游标句炳,这就意味着必须首先创建一个空
Blob/Clob
字段,在丛空
Blob/Clob
获取游标,然后写入我们期望的数据。
 
首先看一下采用传统
JDBC
进行操作的代码:
//….
获取
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()
方法构造空
Blob/Clob
对象
prestmt.setBlob(4,oracle.sql.BLOB.empty_lob());
prestmt.setClob(5,oracle.sql.CLOB.empty_lob());
prestmt.executeUpdate();
prestmt.close();
//
再次从数据库中获得
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();
//
将二进制数据写入
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”);
//
将更新写回数据库
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();
 
 
以上是传统的采用
JDBC
方式处理,注意他将连接的自动提交属性设置为
false
然后将所有的操作并入一个事务中,然后进行提交,这是处理
Oracle
Blob/Clob
字段的一般机制,所以
Hibernate
的处理就应该模仿
JDBC
的处理方式,因为从某种角度来讲
Hibernate
是对
JDBC
的封装因为它的底层访问机制仍然是基于
JDBC
的。
 
Hibernate
的处理:
TUser user=new TUser();
user.setAge(new Integer(26));
user.setName(“zx”);
//
创建空
Blob/Clob
对象
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.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
中写入数据
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();
 
在实际应用中,对于
Clob
字段可以简单的将其映射为
String
类型,不过在
Oracle Thin Driver
Clob
字段支持上有欠缺,当
Clob
内容超过
4000
字节时将无法读取,而
Oracle OCI Driver(
需要在本地安装客户端组件
)
则可以完成大容量
Clob
字段操作。
 
对于上面的代码相信作为成熟的工程师来说都闻到一些
bad smell,
如果
Blob/Clob
字段普遍存在的话,那么我们的持久层逻辑可能遍布这种复杂的逻辑,不过不要着急在我即将讲解的客户自定义类中我们将会看到一个解决方案,通过自定义类型我们可以对数据类型的通用性进行抽象,对于
Blob/Clob
字段我们可以定义一种类型并以这种类型作为
Blob/Clob
字段的映射类型。(好了等到下一篇再说吧!)

转载于:https://my.oschina.net/u/187191/blog/128338

你可能感兴趣的文章
Microsoft Excel软件打开文件出现文件的格式与文件扩展名指定格式不一致?
查看>>
ios ble 参考
查看>>
[转]Pass a ViewBag instance to a HiddenFor field in Razor
查看>>
linux中注册系统服务—service命令的原理通俗
查看>>
基于托管C++的增删改查及异步回调小程序
查看>>
Oracle DBMS_STATS 包 和 Analyze 命令的区别
查看>>
给Visual Studio 2010中文版添加Windows Phone 7模板
查看>>
linux下基本命令
查看>>
windows server 2008R2 上安装配置freesshd
查看>>
手动删除SVCH0ST.EXE的方法
查看>>
已释放的栈内存
查看>>
Android网络之数据解析----SAX方式解析XML数据
查看>>
Java递归列出所有文件和文件夹
查看>>
[关于SQL]查询成绩都大于80分的学生
查看>>
Delphi(Tuxedo,BDE,ADO)三合一数据集组件HsTxQuery
查看>>
java之ibatis数据缓存
查看>>
“TNS-03505:无法解析名称”问题解决一例
查看>>
LeetCode - Longest Common Prefix
查看>>
Android图片处理
查看>>
2015年第21本:万万没想到,用理工科思维理解世界
查看>>