mybatis的BLOB存储与读取
http://blog.csdn.net/luyinchangdejiqing/article/details/45096689
简单介绍一下背景环境,web开发避免不了照片附件之类的东东,原先是存到硬盘的文件下,存储读取都比较方便。现在公司弄了个硬件负载均衡,6台服务器,当用户登录的时候会随机分配到其中的一台机器上,6台机器安装的相同的server,session不共享。访问的同一个oracle11.2g,这样的话,原先的附件就可能不好使了,必须保证6台机器共享文件,想想直接放到数据库里吧,将来再做个本地缓存之类的。ok背景就到这里。
第一步,没做过大字段的存取,网上查资料,N多资料,总体来说有用的不多,但也要硬着头皮找,开始看mybatis和数据库的字段对照表,bytes[]对应的是blob字段,于是在pojo类中的content设置类型为byte[],mapper.xml中设置了resultMap,字段content设置<result property="content" column="content" jdbcType="BLOB" typeHandler="com.ibatis.sqlmap.engine.type.BlobTypeHandlerCallback"/>
结果总是报”ora-01461“的错误,网上查询了一下,基本意思就是超出长度了。但是明明是大字段,图片大小也就是70k,不可能超出长度
1)人为把byte定义一个长度 byte[0] = 1,继续插入数据库,成功!但是这不符合我的需求,这哪是大字段
2)继续网上搜索,说是用byte[]这种形式传的话,1000-2000之间的字节会报‘ora-01461’的错误,网上有给出编写oracleLobHandler的做法,不过他用的是hibernate,大字段是clob,处于懒人目的直接忽略
3)终于找到一篇有用的文章,我的大体里程也是按照他的方法来的http://www.360doc.com/content/06/0913/13/6272_206215.shtml,总结一下里面提到的
1》pojo类中不能使用byte[],也不能使用BLOB,这两种鄙人也都用过确实无效,使用Object
2》mapper.mxl中的resultMap把typeHandler去掉,我也怀疑自带的这个类型处理器不是很好使,不能将blob转换成byte[]等,这里建议有时间的同学可以自己写一个再试试,感觉应该是能成功的,不然换成Object强制类型转换估计也没戏。
3》oracle存大数据的时候,要先插入一个empty_blob()占位符,占到blob字段,其次在查询出来这个大字段用流的方式写入。
4》在进行流读取的时候,发现blob.getBinaryOutputStream();已经过时了,于是改成了推荐的blob.setBinaryStream(0);发现总是提示"无效的参数...",经查看发现是oracle驱动的问题,当时的环境是oracle11.2g+ojdbc6.jar+jdk1.6,查看setBinaryStream这个api说适用于jdbc3.0,按理说都应该满足了,经替换发现,ojdbc6,ojdbc5都出问题,换成支持1.4jdk的ojdbc14.jar不会出问题,但是驱动越高,效率越高,bug越少,所以一直用的过时的方法。
下面把我存储和读取的主要代码附上:
pojo类:
- public class Attachment {
 - private String id;
 - private String group;//分类的id,包括消息附件、照片等
 - private String name;
 - private String type;
 - private String size;
 - private String author;
 - private Object content;
 - public Object getContent() {
 - return content;
 - }
 - public void setContent(Object content) {
 - this.content = content;
 - }
 - public String getId() {
 - return id;
 - }
 - public void setId(String id) {
 - this.id = id;
 - }
 - public String getGroup() {
 - return group;
 - }
 - public void setGroup(String group) {
 - this.group = group;
 - }
 - public String getName() {
 - return name;
 - }
 - public void setName(String name) {
 - this.name = name;
 - }
 - public String getType() {
 - return type;
 - }
 - public void setType(String type) {
 - this.type = type;
 - }
 - public String getSize() {
 - return size;
 - }
 - public void setSize(String size) {
 - this.size = size;
 - }
 - public String getAuthor() {
 - return author;
 - }
 - public void setAuthor(String author) {
 - this.author = author;
 - }
 - }
 
- public class Attachment {
 - private String id;
 - private String group;//分类的id,包括消息附件、照片等
 - private String name;
 - private String type;
 - private String size;
 - private String author;
 - private Object content;
 - public Object getContent() {
 - return content;
 - }
 - public void setContent(Object content) {
 - this.content = content;
 - }
 - public String getId() {
 - return id;
 - }
 - public void setId(String id) {
 - this.id = id;
 - }
 - public String getGroup() {
 - return group;
 - }
 - public void setGroup(String group) {
 - this.group = group;
 - }
 - public String getName() {
 - return name;
 - }
 - public void setName(String name) {
 - this.name = name;
 - }
 - public String getType() {
 - return type;
 - }
 - public void setType(String type) {
 - this.type = type;
 - }
 - public String getSize() {
 - return size;
 - }
 - public void setSize(String size) {
 - this.size = size;
 - }
 - public String getAuthor() {
 - return author;
 - }
 - public void setAuthor(String author) {
 - this.author = author;
 - }
 - }
 
- map.xml中的resultMap和sql:
 
- map.xml中的resultMap和sql:
 
- <resultMap id="attachmentResultMap" type="attachment">
 - <result property="id" column="id"/>
 - <result property="group" column="groupId"/>
 - <result property="name" column="fileName" />
 - <result property="type" column="fileType" />
 - <result property="size" column="fileSize" />
 - <result property="author" column="author" />
 - <result property="content" column="content" jdbcType="BLOB" />
 - </resultMap>
 - <insert id="insertAttachment" parameterType="attachment">
 - insert into bop_attachment (id,filename,filetype,filesize,author,content,groupid)
 - values(#{id},#{name},#{type},#{size},#{author},empty_blob(),#{group})
 - </insert>
 
- <resultMap id="attachmentResultMap" type="attachment">
 - <result property="id" column="id"/>
 - <result property="group" column="groupId"/>
 - <result property="name" column="fileName" />
 - <result property="type" column="fileType" />
 - <result property="size" column="fileSize" />
 - <result property="author" column="author" />
 - <result property="content" column="content" jdbcType="BLOB" />
 - </resultMap>
 - <insert id="insertAttachment" parameterType="attachment">
 - insert into bop_attachment (id,filename,filetype,filesize,author,content,groupid)
 - values(#{id},#{name},#{type},#{size},#{author},empty_blob(),#{group})
 - </insert>
 
service层存储的主要方法:
- @Override
 - public void insertAttachment(Attachment attachment,File file)
 - throws AttachmentServiceException {
 - attachmentDao.insertAttachment(attachment);
 - Attachment att = attachmentDao.queryAttachmentById(attachment.getId());
 - BLOB content = (BLOB)att.getContent();
 - FileInputStream fis = null;
 - OutputStream ops = null;
 - try {
 - ops = content.getBinaryOutputStream();//暂时使用这个废弃的方法
 - //ops = content.setBinaryStream(0);//ojdbc14支持,ojdbc6,5都不支持
 - fis = new FileInputStream(file);
 - byte[] data = null;
 - data = FileCopyUtils.copyToByteArray(fis);
 - ops.write(data);
 - } catch (Exception e) {
 - e.printStackTrace();
 - } finally {
 - try {
 - if(fis!=null){
 - fis.close();
 - }
 - if(ops!=null){
 - ops.close();
 - }
 - } catch (IOException e) {
 - e.printStackTrace();
 - }
 - }
 - }
 
- @Override
 - public void insertAttachment(Attachment attachment,File file)
 - throws AttachmentServiceException {
 - attachmentDao.insertAttachment(attachment);
 - Attachment att = attachmentDao.queryAttachmentById(attachment.getId());
 - BLOB content = (BLOB)att.getContent();
 - FileInputStream fis = null;
 - OutputStream ops = null;
 - try {
 - ops = content.getBinaryOutputStream();//暂时使用这个废弃的方法
 - //ops = content.setBinaryStream(0);//ojdbc14支持,ojdbc6,5都不支持
 - fis = new FileInputStream(file);
 - byte[] data = null;
 - data = FileCopyUtils.copyToByteArray(fis);
 - ops.write(data);
 - } catch (Exception e) {
 - e.printStackTrace();
 - } finally {
 - try {
 - if(fis!=null){
 - fis.close();
 - }
 - if(ops!=null){
 - ops.close();
 - }
 - } catch (IOException e) {
 - e.printStackTrace();
 - }
 - }
 - }
 
用于图片展示的servlet层:
- AttachmentService as = (AttachmentService) SpringUtils.getContext().getBean("AttachmentService");
 - Attachment attachment = null;
 - try {
 - attachment = as.queryAttachmentById(attachmentId);
 - } catch (AttachmentServiceException ae) {
 - logger.error(ae);
 - throw new ServletException(ae);
 - }
 - //String realPath = rootDir + attachment.getName();
 - response.setContentType(attachment.getType());
 - response.setContentLength(Integer.parseInt(attachment.getSize()));
 - response.setHeader("Content-Disposition", "attachment; filename="
 - + java.net.URLEncoder.encode(attachment.getName(), "UTF-8")
 - + ';');
 - InputStream in = null;
 - BLOB content = (BLOB)attachment.getContent();
 - try {
 - in=content.getBinaryStream();
 - } catch (SQLException e) {
 - e.printStackTrace();
 - }
 - BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
 - int n;
 - while ((n=in.read())!=-1){
 - bos.write(n);
 - }
 - bos.flush();
 - bos.close();
 - in.close();
 
mybatis的BLOB存储与读取的更多相关文章
- mybatis oracle BLOB类型字段保存与读取
		
一.BLOB字段 BLOB是指二进制大对象也就是英文Binary Large Object的所写,而CLOB是指大字符对象也就是英文Character Large Object的所写.其中BLOB是用 ...
 - 在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除。
		
在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除. 作者:邵盛松 2009-09-05 前言 1关于的BLOB(Binary)数据的存储和读取功能主要参考了MSDN上的一篇& ...
 - blob的存储与读取
		
对于oracle数据库的blob的存储与读取对应的是byte数组. 将blob类型数据存入数据库: String blob: byte[] byte = blob.getBytes(); entity ...
 - SQLite数据库如何存储和读取二进制数据
		
SQLite数据库如何存储和读取二进制数据 1. 存储二进制数据 SQLite提供的绑定二进制参数接口函数为: int sqlite3_bind_blob(sqlite3_stmt*, int, co ...
 - Android 使用SQLite存储以及读取Drawable对象
		
在进行Android开发过程中,我们经常会接触到Drawable对象,那么,若要使用数据库来进行存储及读取,该如何实现? 一.存储 //第一步,将Drawable对象转化为Bitmap对象 Bitma ...
 - 使用 SharedPreferences 实现数据的存储和读取
		
在开发的过程中我们必须遇到的就是如何对用户的数据进行有效的存储以及读取.我们举个例子,现在我们使用app,当我们登陆一个账号的时候选择记住密码软件就会记住我们的账号以及密码,我们退出当前账号,就可以直 ...
 - 微软Azure云主机及blob存储的网络性能测试
		
http://www.cnblogs.com/sennly/p/4137024.html 微软Azure云主机及blob存储的网络性能测试 1. 测试目的 本次测试的目的在于对微软Azure的云主机. ...
 - paip.odbc DSN的存储与读取
		
paip.odbc DSN的存储与读取 作者Attilax , EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.net/atti ...
 - 在IOS中使用DES算法对Sqlite数据库进行内容加密存储并读取解密
		
在IOS中使用DES算法对Sqlite 数据库进行内容加密存储并读取解密 涉及知识点: 1.DES加密算法: 2.OC对Sqlite数据库的读写: 3.IOS APP文件存储的两种方式及读取方式. 以 ...
 
随机推荐
- java 架构师思维导图
			
java 基础 . 理解IO.多线程.集合等基础框架.对JVM原理有一定了解. spring spring boot ibatis structs开源框架了解. 熟悉分布式系统设计和应用. 小 ...
 - 在Winform中屏蔽UnityWebPlayer的右键以及自带Logo解决方案整理
			
根据项目的需要,对已经完成的Unity三维模型以及游戏要使用Winform进行包装,也就是使用Winform做一层外壳.因此在展示Unity的时候使用到了UnityWebPlayer这个插件,对于此插 ...
 - VUE数组操作方法的局限
			
1.不能通过索引值直接设置一个项: vm.items[indexOfItem] = newValue 但是可以用set方法设置: Vue.set(example1.items,indexOfItem, ...
 - python笔记5  接口类抽象类  封装 反射 设计模式  模块 :random随机数  josn  shelve持久化存储
			
接口类抽象类 接口类:接口类就是制定一个规则,让其他人按照我的规则去写程序. #!/usr/bin/env python from abc import ABCMeta,abstractmethod ...
 - Cinder LVM Oversubscription in thin provisioning
			
目录 文章目录 目录 Oversubscription in thin provisioning Oversubscription in thin provisioning Cinder spec: ...
 - DSS分发压力实验
			
DSS分发压力实验 昨天为验证依托DSS搭建流媒体直播监控系统的可行性,及确定实时流画面出现严重花屏的原因,做了一个压力实验. 网络拓扑如图: 1.DVR上配置4路视频(CIF / 25fps / 1 ...
 - Unity3d Terrain splat 9 is null 解决方法
			
是因为地形的 材质刷和树木或者草的刷子丢失引起.重新赋值或者删除掉就可以了
 - 解决Linux:Too many levels of symbolic links
			
Too many levels of symbolic links 解决:创建链接时使用绝对路径
 - 从物联网防火墙himqtt源码谈哈希和红黑树的应用场景区别
			
从物联网防火墙himqtt源码谈哈希和红黑树的应用场景区别 himqtt是首款完整源码的高性能MQTT物联网防火墙 - MQTT Application FireWall,C语言编写,很多数据结构适合 ...
 - SSRF小梳理
			
SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由攻击者构造形成由服务端发起请求的一个安全漏洞.一般情况下,SSRF攻击的目标是从外网无法访问的内部系统.(正 ...