代码的目的是先将一个配置类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 反序列化错误的更多相关文章

  1. 未指定的错误,发生了一个 Oracle 错误,但无法从 Oracle 中检索错误信息。数据类型不被支持。

    未指定的错误,发生了一个 Oracle 错误,但无法从 Oracle 中检索错误信息.数据类型不被支持. 博客分类: 雅芳生涯 .Net VB C# OracleMicrosoftSecurity  ...

  2. Oracle OCI-22053:溢出错误解决方法

    原文 Oracle OCI-22053:溢出错误解决方法 Oracle 数值数据类型最多可存储 38 个字节的精度.当将 Oracle 数值转换为公共语言运行库数据类型时,小数点后边的位数可能过多,这 ...

  3. Oracle Blob查询和插入

    注:本文来源于<Oracle Blob查询和插入> 插入 UPDATE cmm05 SET OUTFILE = to_blob('12345690'): 查询: SELECT utl_ra ...

  4. Oracle LISTENER 主机名修改为IP地址后LISTENER无法监听到实例 oracle监听错误与hosts文件配置

    为什么listener.ora文件里面HOST后面到底应该输入IP地址还是主机名.我的经验告诉我,这边最好使用主机名.很多的时候,一个机器绑定的不只一个IP地址,如HOST后面是IP地址,那么ORAC ...

  5. Oracle安装连接常见错误

    oracle安装注意:安装路径url不能带中文C:\app\59428\product\11.2.0\dbhome_1\sqldeveloper打开sqldeveloper的时候,需要输入java.e ...

  6. Oracle Blob数据保存为文件

    好久不写文,最近得空写一点.Oracle数据库国内用户量主要在企业上,其中有一种byte的存储称为Blob,并不能直接看. 有时候为了调试需要,可以通过: ,)) ; 这种sql去转为字符串查看,但是 ...

  7. PLSQL Developer 连接oracle(64) (instantclient)错误及解决方案

    安装了PLSQL Developer 64bit,下载地址http://cy1.mqego.com/plsqldeveloperxx.zip. 1.安装完成后,输入数据库连接信息之后,提示如下错误 原 ...

  8. Oracle协议适配器错误解决办法

    在Oracle中新建了一个数据库,今天把它删了之后再登录SQL*PLUS就登不上去了,出现ORA-12560:TNS:协议适配器错误. ORA-12560: TNS: 协议适配器错误的解决方法 造成O ...

  9. EF6 连接Oracle 迁移数据错误解决方法

    环境:vs2015 + EF6 +ODP 数据库Oracle 11G add-migratioin 正常,但在update-database 时报如下错误: System.Runtime.Serial ...

随机推荐

  1. 单调栈 && 洛谷 P2866 [USACO06NOV]糟糕的一天Bad Hair Day(单调栈)

    传送门 这是一道典型的单调栈. 题意理解 先来理解一下题意(原文翻译得有点问题). 其实就是求对于序列中的每一个数i,求出i到它右边第一个大于i的数之间的数字个数c[i].最后求出和. 首先可以暴力求 ...

  2. HDU2188选拔自愿者

    悼念512汶川大地震遇难同胞--选拔志愿者 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  3. R语言基础篇——数据对象

    1.基本数据类型(numeric,logical,character,NA,double,complex,integer) 2.日期变量 常用函数 Sys.Date()-返回系统当前的日期,Sys.t ...

  4. C# 图片与Base64的相互转化

    public ActionResult UploadSignature2(string src_data) { Class1.Base64StrToImage(src_data, "C:\\ ...

  5. 定制团队自己的 Vue template

    一,我们使用vue-cli 可以快速初始化vue.js的项目,官方提供了webpack,pwa,browserify-sipmple,等常用template 二.置知识1,模板结构template:该 ...

  6. Bootstrap框架如何设置导入链接

    bootstrap文件划分: 导入规则: 方式一:可以先下载 ----https://v3.bootcss.com/ (1) 注意事项: (2) (3) 注意1:bootstrap中的js文件依赖于j ...

  7. ubuntu18.04 设置环境变量

    1.第一步:命令行输入 sudo gedit /etc/profile 2.第二步:将你想要设置环境变量的内容追加到文件结尾 例如:export JAVA_HOME=/usr/java/latest ...

  8. linux机器间建立信任关系

    linux机器间建立信任关系 如何建立信任关系 在shell脚本中,需要使用scp命令将本地的文件复制到另一台机器中备份.但通常执行scp命令后都需要输入用户密码,这样在定时自动执行shell脚本中就 ...

  9. 解决 pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([Errno 61] Conne

    pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([Errno 61] ...

  10. 【leetcode】1034. Coloring A Border

    题目如下: Given a 2-dimensional grid of integers, each value in the grid represents the color of the gri ...