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 ...
随机推荐
- [Python3] 015 冰冻集合的内置方法
目录 0. 前言 英文名 元素要求 使用限制 返回 方法数量 1. 如何查看 frozenset() 的内置方法 2. 少废话,上例子 2.1 copy() 2.2 difference() 2.3 ...
- java静态代码块,构造方法,初始化块的执行顺序
代码Parent和Sub进行讲解 public class Parent { private static final String name; public Parent() { System.ou ...
- selenium 定位方式
在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素句柄来定位元素.其中By类的常用定位方式共八种,现分别介绍如下 ...
- 06-JavaScript简介
### 前段三大块 ```HTML css JavaScript``` ### 什么是JavaScript? JavaScript是运行在浏览器端的脚步语言,JavaScript主要解决的是前端与用户 ...
- neovim初次安装使用
github下载neovim代码 按readme中安装,中间可能 要安装一些库 将vim的配置关联到nvim,发现和vim是一样的 ln -s ~/.vim ~/.config/nvim ln -s ...
- 5-基于TMS320C6678+XC7K325T的6U CPCIe高性能处理平台
基于TMS320C6678+XC7K325T的6U CPCIe高性能处理平台 一.板卡概述 本板卡系自主研发,基于CPCI 6U架构,符合CPCI2.0标准.采用 DSP TMS320C66 ...
- wangeditor 支持上传视频版
1.关于使用哪个富文本编辑器. 简单的要求,不要求发布出来的文章排版要求很高. 可用wangediter.(简单,体积小,不可修改上传图片的尺寸大小) 转载 来源: https://blog.csd ...
- $LCT$维护子树信息学习笔记
\(LCT\)维护子树信息学习笔记 昨天\(FDF\)好题分享投了 \([ZJOI2018]\)历史 这题. 然后我顺势学学这个姿势. 结果调了一年...于是写个笔记记录一下. 基本原理 比较显然地, ...
- CentOS安装Git服务器 Centos 6.5 + Git 1.7.1.0 + gitosis
1.安装扩展 yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel 2.下载git ...
- Mybatis(三)MyBatis 注解方式的基本 用法
在 MyBatis注解 SQL 中,最基本的就是@Select.@Insert.@Update 和@Delete 四种.