代码的目的是先将一个配置类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. Samba服务问答

    1. samba服务用在什么地方?samba服务用于把Linux服务器上的文件或者打印接共享给windows或者Linux. 2. 在samba服务的配置文件中,[global]配置部分的securi ...

  2. Java-Lambda表达式第二篇认识Lambda表达式

    接上面的方法引用和构造器引用: 3>引用某类对象的实例方法 @FunctionalInterface public interface Cut{ String cut(String str,in ...

  3. dfs找环

    http://acm.hdu.edu.cn/showproblem.php?pid=6736 Forest Program Time Limit: 2000/1000 MS (Java/Others) ...

  4. Flutter 初探 -

    flutter 安装 经过许久的关注,及最近google算是真正地推行flutter时,加上掘金小册也有相应的教程,我知道自己得跟着这一波潮流学习了,不然迟早会面临着小程序的危(大家都会了就你不会), ...

  5. SQL 常用语句(一)

    --SQL 语句为表添加字段并设置默认值 alter table TableName add ColumnName int --字段类型 not null --是否为空 --默认值 --SQL 语句为 ...

  6. ECarts 的初步使用

    ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等) ...

  7. vue的v-cloak 指令设置样式

    使用 v-cloak 指令设置样式,可以使样式在 Vue 实例编译结束时,从绑定的 HTML 元素上被移除. 详情请参考:https://www.jianshu.com/p/f56cde007210? ...

  8. 03scikit-learn非监督学习

    In [1]: from sklearn.decomposition import PCA from sklearn.datasets import load_iris pca = PCA(n_com ...

  9. GNU linker script,ld script,GNU链接脚本

    https://blog.csdn.net/itxiebo/article/details/50937412 https://blog.csdn.net/itxiebo/article/details ...

  10. 英国已有500万宽带用户接入并开始使用IPv6技术

    2018年英国首家为客户提供IPv6的主要ISP.随着所有现有的符合条件的用户线路启用,约90%的固定宽带用户群接入并开始使用IPv6,为IPv6互联网增加了超过500万个新眼球. 英国IPv6项目于 ...