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文件存储的两种方式及读取方式. 以 ...
随机推荐
- mysql 使用service mysqld start 提示未识别服务 进入/etc/rc.d/init.d 下面未发现有mysqld解决方法
1.执行whereis mysql会有如下打印: mysql: /usr/bin/mysql /usr/lib64/mysql /usr/include/mysql /usr/share/mysql ...
- tomcat 启动报错org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].xxx
今天在写完一个非常简单的servlet页面跳转的web项目后,启动tomcat报错org.apache.catalina.LifecycleException: Failed to start com ...
- Git missing Change-Id in commit message footer解决方法
Git missing Change-Id in commit message footer解决方法在Git向服务器提交代码时,出现如下错误missing Change-Id in commit me ...
- Android控件RecyclerView的基本用法
Android控件RecyclerView的基本用法 转 https://www.jianshu.com/p/e71a4b73098f github: https://github.com/Cym ...
- PC通过netsh获取wifi密码
1.查看当前系统所有保存wifi的ssid netsh wlan show profiles 2.根据指定ssid查看wifi密码,密码就是关键内容 netsh wlan show profile n ...
- AlarmManager(闹钟服务)
1.Timer类与AlarmManager类区别: 对Timer就是定时器,一般写定时任务的时候 肯定离不开他,但是在Android里,他却有个短板,不太适合那些需要长时间在后台运行的 定时任务,因为 ...
- Swift 可选链
可选链(Optional Chaining)是一种可以请求和调用属性.方法和子脚本的过程,用于请求或调用的目标可能为nil. 可选链返回两个值: 如果目标有值,调用就会成功,返回该值 如果目标为nil ...
- scikit-learn机器学习(二)逻辑回归进行二分类(垃圾邮件分类),二分类性能指标,画ROC曲线,计算acc,recall,presicion,f1
数据来自UCI机器学习仓库中的垃圾信息数据集 数据可从http://archive.ics.uci.edu/ml/datasets/sms+spam+collection下载 转成csv载入数据 im ...
- SpringBoot: 17.热部署配置(转)
spring为开发者提供了一个名为spring-boot-devtools的模块来使Spring Boot应用支持热部署,提高开发者的开发效率,无需手动重启Spring Boot应用. devtool ...
- 热更新之lua框架设计
目前中大型游戏项目包含部分VR与AR项目,都需要热更新与在线修改Bug等功能实现,虽然Xlua等插件已经给出了关于C#与Lua语言之间的双向无缝调用实现,但是就热更新的架构却没有提出,这需要广大游戏公 ...