oracle blob 反序列化错误
代码的目的是先将一个配置类JobConfig序列化存进Oracle中的Blob中,然后查的时候反序列化出来。
先看一下控制台报错
### Cause: com.audaque.lib.core.exception.AdqRuntimeException: error on getResult; nested exception is java.io.StreamCorruptedException: invalid stream header: 00540001
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:23)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:107)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:98)
at sun.reflect.GeneratedMethodAccessor133.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:354)
... 84 more
Caused by: com.audaque.lib.core.exception.AdqRuntimeException: error on getResult; nested exception is java.io.StreamCorruptedException: invalid stream header: 00540001
at com.audaque.datadiscovery.mybatis.SerializeHandler.getResult(SerializeHandler.java:50)
at org.apache.ibatis.executor.resultset.FastResultSetHandler.getPropertyMappingValue(FastResultSetHandler.java:325)
at org.apache.ibatis.executor.resultset.FastResultSetHandler.applyPropertyMappings(FastResultSetHandler.java:301)
at org.apache.ibatis.executor.resultset.NestedResultSetHandler.getRowValue(NestedResultSetHandler.java:135)
at org.apache.ibatis.executor.resultset.NestedResultSetHandler.handleRowValues(NestedResultSetHandler.java:102)
at org.apache.ibatis.executor.resultset.FastResultSetHandler.handleResultSet(FastResultSetHandler.java:188)
at org.apache.ibatis.executor.resultset.NestedResultSetHandler.handleResultSet(NestedResultSetHandler.java:73)
Mybatis resultMap
<resultMap type="com.audaque.datadiscovery.job.model.po.Job" id="Job">
<id property="jobId" column="JOB_ID" />
<result property="jobName" column="JOB_NAME" />
<result property="createTime" column="CREATE_TIME" />
<result property="description" column="DESCRIPTION" />
<result property="executeTime" column="EXECUTETIME" />
<result property="jobConfig" column="JOB_CONFIG" typeHandler="com.audaque.datadiscovery.mybatis.SerializeHandler" />
<association property="creator" columnPrefix="creator_" resultMap="User" />
</resultMap>
报错原因是查询后设置结果时,Job对象的JobConfig属性反序列化失败。
使用的是MyBatis框架,针对这个JobConfig 配置类,做了一个TypeHanlder,下面是这个TypeHandlder
public class SerializeHandler implements TypeHandler<Object> {
@Override
public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
ps.setString(i, null);
return;
}
try {
byte[] ss = SerializeUtils.serializeObject(parameter);
ps.setBytes(i, ss);
} catch (IOException e) {
throw new AdqRuntimeException("error on setParameter" ,e);
}
}
@Override
public Object getResult(ResultSet rs, String columnName) throws SQLException {
Object object = null;
try {
//反序列化报错
object = SerializeUtils.deserializeObject(rs.getBytes(columnName));
} catch (IOException e) {
throw new AdqRuntimeException("error on getResult" ,e);
} catch (ClassNotFoundException e) {
throw new AdqRuntimeException("error on getResult" ,e);
}
return object;
}
@Override
public Object getResult(CallableStatement cs, int columnIndex)
throws SQLException {
Object object = null;
try {
object = SerializeUtils.deserializeObject(cs.getBytes(columnIndex));
} catch (IOException e) {
throw new AdqRuntimeException("error on getResult" ,e);
} catch (ClassNotFoundException e) {
throw new AdqRuntimeException("error on getResult" ,e);
}
return object;
}
@Override
public Object getResult(ResultSet rs, int columnIndex) throws SQLException {
Object object = null;
try {
object = SerializeUtils.deserializeObject(rs.getBytes(columnIndex));
} catch (IOException e) {
throw new AdqRuntimeException("error on getResult" ,e);
} catch (ClassNotFoundException e) {
throw new AdqRuntimeException("error on getResult" ,e);
}
return object;
}
}
TypeHandler中有一个序列化工具类
public final class SerializeUtils {
/**
*
* @param object is want to serialize
* @return
* @throws IOException
*/
public static <T> byte[] serializeObject(T object) throws IOException {
byte[] buffer = null;
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
long start = System.currentTimeMillis();
try{
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(object);
oos.flush();
buffer = bos.toByteArray();
}catch(IOException ex){
throw ex;
}finally{
if(oos != null){
oos.close();
}
if(bos != null){
bos.close();
}
long end = System.currentTimeMillis();
// System.out.println("serializeObject "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(start))+" costs "+(end-start) + " ms");
}
return buffer;
}
/**
*
* @param buf is want to deserialize
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
@SuppressWarnings({ "unchecked" })
public static <T> T deserializeObject(byte[] buf) throws IOException, ClassNotFoundException {
T object = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
long start = System.currentTimeMillis();
try{
bis = new ByteArrayInputStream(buf);
ois = new ObjectInputStream(bis);
object = (T) ois.readObject();
}catch(IOException ex){
throw ex;
}finally{
if(ois != null){
ois.close();
}
if(bis != null){
bis.close();
}
long end = System.currentTimeMillis();
// System.out.println("deserializeObject "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(start))+" costs "+(end-start) + " ms");
}
return object;
}
我先测试了工具类SerializeUtils是否有问题,测试了一下是没有问题的。
我在序列化之后调用反序列化方法,也是没有问题的。
问题出在从数据库查询出来后,查了一下读取BLOB对象为byte的java代码,java.sql.Blob对象转化byte数组 和 oracle.sql.Blob对象转化byte数组的方法不同,如果使用 oracle.sql.Blob.getBytes方法转化,则会报java.io.StreamCorruptedException: invalid stream header: 006C0001 错误
QueryRunner run = new QueryRunner(true);
String querySql = "SELECT JOB_CONFIG FROM adqm_job where job_id = 141";
Object[] array = run.query(con, querySql, new ArrayHandler());
Blob blob= (Blob) array[0];
byte[] returnValue = blob.getBytes(1, (int) blob.length());
System.out.println(Arrays.toString(returnValue));
InputStream is = null;
BLOB blob1 = (BLOB)(array[0]);
byte[] b = null;
try {
is = blob1.getBinaryStream();
b = new byte[(int) blob1.length()];
is.read(b);
} catch (Exception e) {
e.printStackTrace();
}
但是系统代码使用的是 rs.getBytes(columnName)代码,那是否是getBytes代码有问题吗?
Connection con = DBUtil.getConnection();
String querySql = "SELECT JOB_CONFIG FROM adqm_job where job_id = 141";
PreparedStatement preparedStatement = con.prepareStatement(querySql);
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next())
{
byte []bytes= resultSet.getBytes("JOB_CONFIG");
SerializeUtils.deserializeObject(bytes);
}
DBUtil.close(con);
测试了一下使用 rs.getBytes(columnName) 取出byte数组是 反序列化是没有问题的。
BUG的原因还是没有找到,我猜想的原因是object = SerializeUtils.deserializeObject(rs.getBytes(columnName)); 中rs.getBytes(columnName)的底层实现为((BLOB)(rs.getBlob)).getBytes();
最后我将TypeHandler 的getResult方法中改为
@Override
public Object getResult(ResultSet rs, String columnName) throws SQLException {
Object object = null; // 集成工作流BUG修复
try {
Blob blob = rs.getBlob(columnName);
byte[] returnValue = null;
if (null != blob) {
returnValue = blob.getBytes(1, (int) blob.length());
object = SerializeUtils.deserializeObject(returnValue);
}
// 代码
// object = SerializeUtils.deserializeObject(rs.getBytes(columnName)); } catch (IOException e) {
throw new AdqRuntimeException("error on getResult" ,e);
} catch (ClassNotFoundException e) {
throw new AdqRuntimeException("error on getResult" ,e);
}
return object;
}
就能正确反序列化了
oracle blob 反序列化错误的更多相关文章
- 未指定的错误,发生了一个 Oracle 错误,但无法从 Oracle 中检索错误信息。数据类型不被支持。
未指定的错误,发生了一个 Oracle 错误,但无法从 Oracle 中检索错误信息.数据类型不被支持. 博客分类: 雅芳生涯 .Net VB C# OracleMicrosoftSecurity ...
- Oracle OCI-22053:溢出错误解决方法
原文 Oracle OCI-22053:溢出错误解决方法 Oracle 数值数据类型最多可存储 38 个字节的精度.当将 Oracle 数值转换为公共语言运行库数据类型时,小数点后边的位数可能过多,这 ...
- Oracle Blob查询和插入
注:本文来源于<Oracle Blob查询和插入> 插入 UPDATE cmm05 SET OUTFILE = to_blob('12345690'): 查询: SELECT utl_ra ...
- Oracle LISTENER 主机名修改为IP地址后LISTENER无法监听到实例 oracle监听错误与hosts文件配置
为什么listener.ora文件里面HOST后面到底应该输入IP地址还是主机名.我的经验告诉我,这边最好使用主机名.很多的时候,一个机器绑定的不只一个IP地址,如HOST后面是IP地址,那么ORAC ...
- Oracle安装连接常见错误
oracle安装注意:安装路径url不能带中文C:\app\59428\product\11.2.0\dbhome_1\sqldeveloper打开sqldeveloper的时候,需要输入java.e ...
- Oracle Blob数据保存为文件
好久不写文,最近得空写一点.Oracle数据库国内用户量主要在企业上,其中有一种byte的存储称为Blob,并不能直接看. 有时候为了调试需要,可以通过: ,)) ; 这种sql去转为字符串查看,但是 ...
- PLSQL Developer 连接oracle(64) (instantclient)错误及解决方案
安装了PLSQL Developer 64bit,下载地址http://cy1.mqego.com/plsqldeveloperxx.zip. 1.安装完成后,输入数据库连接信息之后,提示如下错误 原 ...
- Oracle协议适配器错误解决办法
在Oracle中新建了一个数据库,今天把它删了之后再登录SQL*PLUS就登不上去了,出现ORA-12560:TNS:协议适配器错误. ORA-12560: TNS: 协议适配器错误的解决方法 造成O ...
- EF6 连接Oracle 迁移数据错误解决方法
环境:vs2015 + EF6 +ODP 数据库Oracle 11G add-migratioin 正常,但在update-database 时报如下错误: System.Runtime.Serial ...
随机推荐
- C#MessageBox 自动关闭窗口
1:MessageBox弹出的模式窗口会先阻塞掉它的父级线程.所以我们可以考虑在MessageBox前先增加一个用于"杀"掉MessageBox窗口的线程.因为需要在规定时间内&q ...
- 极*Java速成教程 - (2)
Java语言基础 Java的一切都是以对象为基础,对象是生是死的生命周期由虚拟机管理,但是在创生和消亡阶段,需要我们去管理这个类怎么生,怎么死.我们也以此为契机,慢慢接触Java的诸多细节和具体实现. ...
- 硬核!如何模拟 5w+ 的并发用户?
来自:http://t.cn/ES7KBkW 本文将从负载测试的角度,描述了做一次流畅的5万用户并发测试需要做的事情. 你可以在本文的结尾部分看到讨论的记录. 快速的步骤概要 编写你的脚本 使用JMe ...
- EOJ Monthly 2019.2 A. 回收卫星
题目传送门 题意: 你可以询问一个三维坐标,机器会告诉你这个坐标在不在目标圆中, 并且(0,0,0)是一定在圆上的,叫你求出圆心坐标 思路: 因为(0,0,0)一定在圆上,所以我们可以把圆心分成3个坐 ...
- python学习第四十四天斐波那契数列和yield关键词使用
斐波那契数列是数学中的常见的算法,第一个第二个不算,从第三个开始,每个数的都是前面两个数的和,使用yield关键词把生成的数列保存起来,调用的时候再调用,下面举例说明一下 def fab(max): ...
- 安装python3并安装pip3
python是一门高级编译语言,这么语言可以让你做一些运维平台,是因为他可以执行linux中的命令,让你实现自动化和半自动话,s 在运维开发这方面的话,就相当于把shell和java给结合了一下,ja ...
- java操作mongodb工具类
新建maven项目 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="ht ...
- 03.LinuxCentOS系统root目录LVM磁盘扩容
根目录LVM扩容操作步骤: [root@centos7 ~]# df -lh文件系统 容量 已用 可用 已用% 挂载点/dev/mapper/centos-root 50G 7.7G 43G 6% / ...
- python内存分析
安装 首先安装memory_profiler和psutil pip install memory_profiler pip install psutil 在需要分析的函数前面添加装饰器@profile ...
- linux使用v 2ray
一.安装配置服务端程序 是时候使用 了,因为相对安全,使用方法很简单,使用root权限执行以下命令即可 $ sudo -i 一顿安装后如图 输入 命令可以查看链接,然后在客户端使用这个链接就能配置好了 ...