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 ...
随机推荐
- Leveldb源码分析--1
coming from http://blog.csdn.net/sparkliang/article/details/8567602 [前言:看了一点oceanbase,没有意志力继续坚持下去了,暂 ...
- Excel VBA批量处理寸照名字(类模块加FSO版)
需求:因为处理学生学籍照片,从照相馆拿回来的寸照是按班级整理好,文件名是相机编号的文件.那么处理的话,是这么一个思路,通过Excel表格打印出各班A4照片列表,让学生自行填上照片对应姓名.表格收回来后 ...
- Educational Codeforces Round 60 (Rated for Div. 2) D. Magic Gems(矩阵快速幂)
题目传送门 题意: 一个魔法水晶可以分裂成m个水晶,求放满n个水晶的方案数(mol1e9+7) 思路: 线性dp,dp[i]=dp[i]+dp[i-m]; 由于n到1e18,所以要用到矩阵快速幂优化 ...
- P3452 [POI2007]BIU-Offices
传送门 首先能想到 $n^2$ 的做法 枚举所有两点,看看是否有边相连,如果没有说明它们一定要在同一集合,用并查集维护一下就行 注意到如果没有边这个条件,其实就相当于问补图有边 所以题意可以转化为,求 ...
- c#用log4Net将日志写入到Oracle数据库,并写入到文件中
原文:c#用log4Net将日志写入到Oracle数据库,并写入到文件中 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https:/ ...
- wepy的第一个demo
一.在node中安装相应的模块文件,查看文档 二.案例 json部分 { "usingComponents": { "van-button": ".. ...
- 表格类型数据,Excel csv导入,导出操作
import pandas # 创建表格格式# ad = pandas.DataFrame({"a": range(1, 10), "b": range(10, ...
- 【转】DDR3和eMMC区别
转自:https://www.cnblogs.com/debruyne/p/9186619.html DDR3内存条和eMMC存储器区别: 1. 存储性质不同:2. 存储容量不同:3. 运行速度不同: ...
- HTTP RESTful服务开发 spring boot+Maven +Swagger
这周配合第三方平台整合系统,需要提供HTTP REST服务和使用ActiveMQ推送消息,研究了下,做个笔记. 1.使用eclipse创建Spring Boot项目 创建Spring Boot项目( ...
- 11JSP基础
1.Jsp基础 1.1 简介 Jsp,全称 Java Server Page java服务页面,能提供java服务的页面 jsp vs html html: 由html标签组成的,输出静态内容. js ...