这两天遇到一个问题,其中项目是将一个老的项目迁移成微服务架构的,用mybatis进行持久层开发;原本是查一个表,只不过其中一个字段执行了一个存储过程,以后要到全业务数据中心后,考虑不跑存储过程了,然后就将存储过程对字段的处理转移到了java代码中,难点在于这是一个blob类型的大字段,在oracle数据库中直接用dbms_lob_substr()函数直接截取需要的字段就可以查处相关的数据,展示的也是字符串,但是到java中通过断点则是[B@69df6c1d,明显这是一个内存地址,我暂时还不太明白为什么显示一个内存地址。
寻求解决办法:使用晚上说的直接读取blob大字段,然后通过流的形式将blob转成二进制数组
private static byte[] blobToBytes(Blob blob) {
BufferedInputStream is = null;
byte[] bytes = null;
try {
is = new BufferedInputStream(blob.getBinaryStream());
bytes = new byte[(int) blob.length()];
int len = bytes.length;
int offset = 0;
int read = 0;
while (offset < len
&& (read = is.read(bytes, offset, len - offset)) >= 0) {
offset += read;
}
} catch (Exception e) {
e.printStackTrace();
}
return bytes;
}
或者将blob大字段转String
String blobString = new String(b.getBytes(1, (int) b.length()),"GBK");//blob 转 String
上面这两种方式都会出现全文乱码(不是中文乱码)
继续尝试网上一种通过mybatis配置直接返回二进制数组的mybatis中加入
这里放下原网址:https://blog.csdn.net/lqzkcx3/article/details/80969105
<!-- 映射文件-->
<resultMap type="map" id="blobResultMap">
<!--为了以示区分, 特意将property配置为和column不一样 -->
<result property="AX_D" column="AX_DATA" jdbcType="BLOB" javaType = "_byte[]"/>
</resultMap>
注意:查询的SQL语句中, 是针对两个字段; 但在resultMap的映射配置中, 我们只设置了一个,也就是只配置了特殊情况——BLOB映射,其他字段的匹配最终还是交给了Mybatis自主完成。
<select> 标签中的属性设置中,我们使用的是resultMap来引用我们配置的<resultMap>,而不是通常的resultType。
<resultMap>的type属性, 我们设置的依然是map,这样可以保证最大的兼容性。
这样是通过数据库查询的blob字段放入我们自己配置的map,进入的是blob,出来的是byte[],按照理想状态是可以的,结果debug出来的是非正常的二进制数组,例如【-1,40,-1,127,-1,0,0,0】
后来想,通过dbms_lob_substr()方法查出来的是字符串,只是不知到为什么显示是内存地址,就想查询结果往map放一边,就改动成
<!-- 映射文件-->
<resultMap type="map" id="blobResultMap">
<!--为了以示区分, 特意将property配置为和column不一样 -->
<result property="AX_D" column="AX_DATA" jdbcType="BLOB" javaType = "String"/>
</resultMap>
这样在查询结果就能正常显示了,例如e8ddd787222;
至此,忙活了一整天的问题得到了解决(其实在处理存储过程的时候也费了好大劲,在sql中实在解决不了才转到java代码中的)