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文件存储的两种方式及读取方式. 以 ...
随机推荐
- js的dom测试及实例代码
js的dom测试及实例代码 一.总结 一句话总结: 1.需要记得 创建 标签和创建文本节点都是document的活:document.createTextNode("Rockets的姚明&q ...
- ArcGIS超级工具SPTOOLS-SHP转数据库,批量数据库转数据库,栅格彩色转黑白
1.1 SHP转数据库 把一个文件夹的数据,转到数据库,或者另一个文件夹,不含字文件夹 1.2 批量数据库转数据库 把一个文件夹下GDB或者MDB,转到另一个文件夹为MDB,GDB,并实现版本的转 ...
- 《你不知道的JavaScript(上)》笔记——动态作用域
动态作用域让作用域作为一个在运行时就被动态确定的形式, 而不是在写代码时进行静态确定的形式.动态作用域并不关心函数和作用域是如何声明以及在何处声明的, 只关心它们从何处调用. 换句话说, 作用域链是基 ...
- 对官网vue事件修饰符串联的顺序如何理解?
官网有一个提醒:使用修饰符时,顺序很重要:相应的代码会以同样的顺序产生.因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent ...
- amm与tmpfs和swap
/dev/shm对Oracle 11g的影响: ORACLE 从11g版本开始,引入了一个自动内存管理(Automatic Memory Management)特性,该特性需要更多的共享内存(/dev ...
- Qt编写数据可视化大屏界面电子看板11-自定义控件
一.前言 说到自定义控件,我是感觉特别熟悉的几个字,本人亲自原创的自定义控件超过110个,都是来自各个行业的具体应用真实需求,而不是凭空捏造的,当然有几个小控件也有点凑数的嫌疑,在编写整个数据可视化大 ...
- MySQL网页端在线查询工具
现在许多应用都移到云服务器上面了,数据库的远程维护.监控成为一大问题,通过TreeSoft数据库管理系统,可以方便的使用浏览器,通过网页操作的方式管理MySQL,Oracle,DB2,PostgreS ...
- Unity 实现橡皮擦效果
我所实现的橡皮擦效果是设置图片某点的像素的透明度为0,来简单实现擦除效果的: 下面是效果 首先需要注意两点:1:设置 Main Camera 的 projection 属性为Orthographic ...
- mysql学习笔记11_18(更新、插入和删除)
1.初始表 mysql> select * from department; 2.修改销售部的地点为杭州 mysql> update department set address = '杭 ...
- 十步学习法 -- 来自<<软技能>>一书的学习方法论
<<软技能>>第三篇“学习”,作者讲述了自己的学习方法:十步学习法.下面我用编程语言的方式来介绍. 十步学习法 伪代码介绍 # **这一步的目的不是要掌握整个主题,而是对相关内 ...