mybatis的BLOB儲存與讀取
來源:互聯網
上載者:User
簡單介紹一下背景環境,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類:
[html] view plaincopy在CODE上查看代碼片派生到My Code片
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;
}
}
[html] view plaincopy在CODE上查看代碼片派生到My Code片
map.xml中的resultMap和sql:
[java] view plaincopy在CODE上查看代碼片派生到My Code片
<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層儲存的主要方法:
[java] view plaincopy在CODE上查看代碼片派生到My Code片
@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層:
[java] view plaincopy在CODE上查看代碼片派生到My Code片
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();
轉載自:http://blog.csdn.net/bluesky5219/article/details/36427789