MySQL BLOB類型數據操作

一、MySQL BLOB 類型介紹
MySQL中,BLOB是一個二進制大型對象,是一個可以存儲大量數據的容器,它能容納不同大小的數據。BLOB類型實際是個類型系列(TinyBlob、Blob、MediumBlob、LongBlob),除了在存儲的最大信息量上不同外,他們是等同的。 

MySQL的四種BLOB類型 
 類型  大小(單位:字節) 
 TinyBlob  最大 255B
 Blob  最大 65K 
 MediumBlob  最大 16M 
 LongBlob  最大 4G 

實際使用中根據需要存入的數據大小定義不同的BLOB類型。 
需要注意的是:如果你存儲的文件過大,數據庫的性能會下降很多。
  

 

二、mysql中的blob存取

create table Dish {

 int id;

blob photo;

};

下面是從數據庫裏寫的方法:

         String filepath = (String)session.getAttribute("file");//這裏獲得的是用jspsmartupload上傳的文件的路徑
          File file = new File(filepath);
          FileInputStream fin = new FileInputStream(file);
      
          dataBS = new blobConn();   
          con = dataBS.getConn();

          String erpsql = "insert into Dish values(?,?)";
          PreparedStatement stmt = con.prepareStatement(erpsql);
          stmt.setString(2,String.valueOf(id));
          stmt.setBinaryStream(3,fin,(int)file.length());//想數據庫裏插入是很簡單的,就一行,但這種方法只有mysql可以用
          stmt.executeUpdate();
                            
          fin.close();
          stmt.close();
          con.close();

下面是從數據庫裏讀的方法:

1.BufferedInputStream inputimg = null;

try {

 Connection con = sqlDS.getConnection();//簡寫,獲得數據庫連接

Statement stmt = con.createStatement();

ResultSet rs = stmt.executeQuery("select from Dish where id = 11");

if(rs.next()){

java.sql.Blob blob = (java.sql.Blob)rs.getBlob("photo");

input = new BufferedInputStream(blob.getBinaryStream);

}

BufferedImage image = null;

image = javax.imageio.ImageIo.read(input);

ServlerOutputStream sos = response.getOutputStream();

JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(sos);

encoder.encode(image);

input.close();

}catch(Exception e) {

e.printStackTrace();

}

 

2.

if(rs.next()){

    res.setContentType ("image/jpeg;charset=GB2312");//HttpServletResponse res
    ServletOutputStream out = res.getOutputStream ();
   
    BufferedInputStream jpgData = new BufferedInputStream (rs.getBinaryStream ("photo"));
    byte [] buf = new byte [4*1024];
    int len;

    if(jpgData.available () <= 0x0)//判斷數據庫裏存放圖片的字段是否有值,可以進行其他處理
     res.sendRedirect ("/images/nophoto.gif"); 
    
    while((len = jpgData.read (buf, 0, buf.length)) != -1)
     out.write (buf, 0, len);

}

3.

if(rs.next()){

        res.setContentType("image/jpeg");  
        ServletOutputStream   out=res.getOutputStream();  
        InputStream   in=rs.getBinaryStream("photo");  
        byte   buff[]=new   byte[1024];  
        int   i;  
        while((i=in.read(buff))!=-1){   
              out.write(buff);  
        }  
        in.close();   
        out.close();

}  

 

三、charset設置對blog操作的影響

存儲txt文件的時候沒有問題;存儲圖片也沒問題,但是再把圖片圖片從數據庫中取出來,不能正常顯示了;存儲word格式的文件報錯,如下:

Caused by: java.sql.BatchUpdateException: Syntax error or access violation message from server: "You have an error in your SQL syntax near ''D0CF11E0A1B11AE1000000000000000000000000000000003E000300FEFF0900060000000000000' at line 1"
    at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:
1540)

查了一下可能是charset編碼的問題,於是將原來的連接字符串設置爲:

Java代碼 複製代碼 收藏代碼
  1. url=url++"?useUnicode=true&characterEncoding=utf-8";  
url=url++"?useUnicode=true&characterEncoding=utf-8";

 問題解決了,不僅能支持各種格式的文件,圖片也顯示正常了。如果設置爲其他的字符集就會出現前面的錯誤。

 

四、max_allowed_packet參數設置

往數據庫中存儲較大的文件是出現如下錯誤:

 

Java代碼 複製代碼 收藏代碼
  1. <STRONG>java.lang.IllegalArgumentException: Packet is larger than max_allowed_packet from server configuration of 1048576 bytes</STRONG>  
java.lang.IllegalArgumentException: Packet is larger than max_allowed_packet from server configuration of 1048576 bytes

這是因爲存入的文件大於mysql默認的 max_allowed_packet值。

解決辦法:在mysql安裝目錄下的my.ini文件中的最後一行添加

Java代碼 複製代碼 收藏代碼
  1. max_allowed_packet = 10M(也可以設置自己需要的大小)。  
max_allowed_packet = 10M(也可以設置自己需要的大小)。

 五、效率問題

利用數據庫存儲大量文件時,查詢效率就會變得很低。

在表的設計上,我們可以選擇吧文件的相關信息存在一個表中fileInfo,而吧文件內容存在另一個表中fileContent,fileContent中有一個指向fileInfo的外鍵。這樣,查詢的時候只需要訪問fileInfo,只有當要訪問某個文件具體內容的時候才訪問fileContent表。分表存儲,能夠顯著提高查詢速度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章