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类:

  1. public class Attachment {
  2. private String id;
  3. private String group;//分类的id,包括消息附件、照片等
  4. private String name;
  5. private String type;
  6. private String size;
  7. private String author;
  8. private Object content;
  9. public Object getContent() {
  10. return content;
  11. }
  12. public void setContent(Object content) {
  13. this.content = content;
  14. }
  15. public String getId() {
  16. return id;
  17. }
  18. public void setId(String id) {
  19. this.id = id;
  20. }
  21. public String getGroup() {
  22. return group;
  23. }
  24. public void setGroup(String group) {
  25. this.group = group;
  26. }
  27. public String getName() {
  28. return name;
  29. }
  30. public void setName(String name) {
  31. this.name = name;
  32. }
  33. public String getType() {
  34. return type;
  35. }
  36. public void setType(String type) {
  37. this.type = type;
  38. }
  39. public String getSize() {
  40. return size;
  41. }
  42. public void setSize(String size) {
  43. this.size = size;
  44. }
  45. public String getAuthor() {
  46. return author;
  47. }
  48. public void setAuthor(String author) {
  49. this.author = author;
  50. }
  51. }
  1. public class Attachment {
  2. private String id;
  3. private String group;//分类的id,包括消息附件、照片等
  4. private String name;
  5. private String type;
  6. private String size;
  7. private String author;
  8. private Object content;
  9. public Object getContent() {
  10. return content;
  11. }
  12. public void setContent(Object content) {
  13. this.content = content;
  14. }
  15. public String getId() {
  16. return id;
  17. }
  18. public void setId(String id) {
  19. this.id = id;
  20. }
  21. public String getGroup() {
  22. return group;
  23. }
  24. public void setGroup(String group) {
  25. this.group = group;
  26. }
  27. public String getName() {
  28. return name;
  29. }
  30. public void setName(String name) {
  31. this.name = name;
  32. }
  33. public String getType() {
  34. return type;
  35. }
  36. public void setType(String type) {
  37. this.type = type;
  38. }
  39. public String getSize() {
  40. return size;
  41. }
  42. public void setSize(String size) {
  43. this.size = size;
  44. }
  45. public String getAuthor() {
  46. return author;
  47. }
  48. public void setAuthor(String author) {
  49. this.author = author;
  50. }
  51. }
  1. map.xml中的resultMap和sql:
  1. map.xml中的resultMap和sql:
  1. <resultMap id="attachmentResultMap" type="attachment">
  2. <result property="id" column="id"/>
  3. <result property="group" column="groupId"/>
  4. <result property="name" column="fileName" />
  5. <result property="type" column="fileType" />
  6. <result property="size" column="fileSize" />
  7. <result property="author" column="author" />
  8. <result property="content" column="content" jdbcType="BLOB" />
  9. </resultMap>
  10. <insert id="insertAttachment" parameterType="attachment">
  11. insert into bop_attachment (id,filename,filetype,filesize,author,content,groupid)
  12. values(#{id},#{name},#{type},#{size},#{author},empty_blob(),#{group})
  13. </insert>
  1. <resultMap id="attachmentResultMap" type="attachment">
  2. <result property="id" column="id"/>
  3. <result property="group" column="groupId"/>
  4. <result property="name" column="fileName" />
  5. <result property="type" column="fileType" />
  6. <result property="size" column="fileSize" />
  7. <result property="author" column="author" />
  8. <result property="content" column="content" jdbcType="BLOB" />
  9. </resultMap>
  10. <insert id="insertAttachment" parameterType="attachment">
  11. insert into bop_attachment (id,filename,filetype,filesize,author,content,groupid)
  12. values(#{id},#{name},#{type},#{size},#{author},empty_blob(),#{group})
  13. </insert>

service层存储的主要方法:

  1. @Override
  2. public void insertAttachment(Attachment attachment,File file)
  3. throws AttachmentServiceException {
  4. attachmentDao.insertAttachment(attachment);
  5. Attachment att = attachmentDao.queryAttachmentById(attachment.getId());
  6. BLOB content = (BLOB)att.getContent();
  7. FileInputStream fis = null;
  8. OutputStream ops = null;
  9. try {
  10. ops = content.getBinaryOutputStream();//暂时使用这个废弃的方法
  11. //ops = content.setBinaryStream(0);//ojdbc14支持,ojdbc6,5都不支持
  12. fis = new FileInputStream(file);
  13. byte[] data = null;
  14. data = FileCopyUtils.copyToByteArray(fis);
  15. ops.write(data);
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. } finally {
  19. try {
  20. if(fis!=null){
  21. fis.close();
  22. }
  23. if(ops!=null){
  24. ops.close();
  25. }
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }
  1. @Override
  2. public void insertAttachment(Attachment attachment,File file)
  3. throws AttachmentServiceException {
  4. attachmentDao.insertAttachment(attachment);
  5. Attachment att = attachmentDao.queryAttachmentById(attachment.getId());
  6. BLOB content = (BLOB)att.getContent();
  7. FileInputStream fis = null;
  8. OutputStream ops = null;
  9. try {
  10. ops = content.getBinaryOutputStream();//暂时使用这个废弃的方法
  11. //ops = content.setBinaryStream(0);//ojdbc14支持,ojdbc6,5都不支持
  12. fis = new FileInputStream(file);
  13. byte[] data = null;
  14. data = FileCopyUtils.copyToByteArray(fis);
  15. ops.write(data);
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. } finally {
  19. try {
  20. if(fis!=null){
  21. fis.close();
  22. }
  23. if(ops!=null){
  24. ops.close();
  25. }
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }

用于图片展示的servlet层:

    1. AttachmentService as = (AttachmentService) SpringUtils.getContext().getBean("AttachmentService");
    2. Attachment attachment = null;
    3. try {
    4. attachment = as.queryAttachmentById(attachmentId);
    5. } catch (AttachmentServiceException ae) {
    6. logger.error(ae);
    7. throw new ServletException(ae);
    8. }
    9. //String realPath = rootDir + attachment.getName();
    10. response.setContentType(attachment.getType());
    11. response.setContentLength(Integer.parseInt(attachment.getSize()));
    12. response.setHeader("Content-Disposition", "attachment; filename="
    13. + java.net.URLEncoder.encode(attachment.getName(), "UTF-8")
    14. + ';');
    15. InputStream in = null;
    16. BLOB content = (BLOB)attachment.getContent();
    17. try {
    18. in=content.getBinaryStream();
    19. } catch (SQLException e) {
    20. e.printStackTrace();
    21. }
    22. BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
    23. int n;
    24. while ((n=in.read())!=-1){
    25. bos.write(n);
    26. }
    27. bos.flush();
    28. bos.close();
    29. in.close();

mybatis的BLOB存储与读取的更多相关文章

  1. mybatis oracle BLOB类型字段保存与读取

    一.BLOB字段 BLOB是指二进制大对象也就是英文Binary Large Object的所写,而CLOB是指大字符对象也就是英文Character Large Object的所写.其中BLOB是用 ...

  2. 在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除。

    在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除. 作者:邵盛松 2009-09-05 前言 1关于的BLOB(Binary)数据的存储和读取功能主要参考了MSDN上的一篇& ...

  3. blob的存储与读取

    对于oracle数据库的blob的存储与读取对应的是byte数组. 将blob类型数据存入数据库: String blob: byte[] byte = blob.getBytes(); entity ...

  4. SQLite数据库如何存储和读取二进制数据

    SQLite数据库如何存储和读取二进制数据 1. 存储二进制数据 SQLite提供的绑定二进制参数接口函数为: int sqlite3_bind_blob(sqlite3_stmt*, int, co ...

  5. Android 使用SQLite存储以及读取Drawable对象

    在进行Android开发过程中,我们经常会接触到Drawable对象,那么,若要使用数据库来进行存储及读取,该如何实现? 一.存储 //第一步,将Drawable对象转化为Bitmap对象 Bitma ...

  6. 使用 SharedPreferences 实现数据的存储和读取

    在开发的过程中我们必须遇到的就是如何对用户的数据进行有效的存储以及读取.我们举个例子,现在我们使用app,当我们登陆一个账号的时候选择记住密码软件就会记住我们的账号以及密码,我们退出当前账号,就可以直 ...

  7. 微软Azure云主机及blob存储的网络性能测试

    http://www.cnblogs.com/sennly/p/4137024.html 微软Azure云主机及blob存储的网络性能测试 1. 测试目的 本次测试的目的在于对微软Azure的云主机. ...

  8. paip.odbc DSN的存储与读取

    paip.odbc DSN的存储与读取 作者Attilax ,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn.net/atti ...

  9. 在IOS中使用DES算法对Sqlite数据库进行内容加密存储并读取解密

    在IOS中使用DES算法对Sqlite 数据库进行内容加密存储并读取解密 涉及知识点: 1.DES加密算法: 2.OC对Sqlite数据库的读写: 3.IOS APP文件存储的两种方式及读取方式. 以 ...

随机推荐

  1. PHP学习之分页类

    <?php $page = new Page(2, 40); var_dump($page->allUrl()); class Page { //每页显示多少条数据 protected $ ...

  2. fcgi vs. gunicorn vs. uWSGI

    fcgi vs. gunicorn vs. uWSGI - Peterbe.comhttps://www.peterbe.com/plog/fcgi-vs-gunicorn-vs-uwsgi uWSG ...

  3. VBA添加下拉菜单

    Sub createMenus() Dim cmdBar As CommandBar Dim cmdMenu As CommandBarPopup Dim cmdBtn As CommandBarBu ...

  4. Java 检查IPv6地址的合法性

    Java 检查IPv6地址的合法性 由于IPv4资源即将耗尽,IPv6将要正式启用,这是大势所趋. 一些现有的服务和应用逐步要对IPv6支持,目前还处在过渡阶段. 提前了解一些IPv6的知识,还是有必 ...

  5. SpringBoot 2.x中为tomcat配置ssl(https)支持

    参考来源:https://www.cnblogs.com/imfjj/p/9058443.html https://blog.csdn.net/jackymvc/article/details/810 ...

  6. 看看可爱c#中的delegate(委托)和event(事件)用法好不好

    一.开篇忏悔 对自己最拿手的编程语言C#,我想对你说声对不起,因为我到现在为止才明白c#中的delegate和event是怎么用的,惭愧那.好了,那今天就趁月黑风高的夜晚简单来谈谈delegate和e ...

  7. 1-3 RHEL7操作系统的安装

    RHEL7操作系统的安装 本节所讲内容: q  RHEL7.2操作系统的安装 第1章 RHEL7系统安装 1.1 安装软件准备: 需要的软件如下: Vmware workstation 12(含注册码 ...

  8. .Netcore 2.0 Ocelot Api网关教程(10)- Headers Transformation

    本文介绍Ocelot中的请求头传递(Headers Transformation),其可以改变上游request传递给下游/下游response传递给上游的header. 1.修改ValuesCont ...

  9. 纯css实现表单输入验证

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. CF1190D Tokitsukaze and Strange Rectangle

    思路: 线段树 + 扫描线. 实现: #include <bits/stdc++.h> using namespace std; typedef long long ll; ; int n ...