Mysql 中的blob相關問題

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


MySQL的四種BLOB類型 
 類型  大小(單位:字節) 
 TinyBlob  最大 255B
 Blob  最大 65K  //個人不是這個大小啊,也許設個是之前的吧
 MediumBlob  最大 16M 
 LongBlob  最大 4G 

實際使用中根據須要存入的數據大小定義不一樣的BLOB類型。 
須要注意的是:若是你存儲的文件過大,數據庫的性能會降低不少。  mysql

 

2、mysql中的blob存取sql

表結構:數據庫

create table Dish {session

     int id;app

     blob photo;jsp

};性能

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

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));
          
//想數據庫裏插入是很簡單的,就一行,但這種方法只有mysql能夠用
stmt.setBinaryStream(3,fin,(int)file.length());
          
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();
}

3、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代碼 

url=url++"?useUnicode=true&characterEncoding=utf-8";

 問題解決了,不只能支持各類格式的文件,圖片也顯示正常了。若是設置爲其餘的字符集就會出現前面的錯誤。

 

4、max_allowed_packet參數設置

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

Java代碼 

<strong>java.lang.IllegalArgumentException: Packet is larger than max_allowed_packet from server configuration of 1048576 bytes</strong>

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

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

Java代碼 

max_allowed_packet = 10M(也能夠設置本身須要的大小)。

 5、效率問題

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

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

 

-------------------------------------------------------------------------------------------------

 

  CLOB類型默認爲1m 若是大於的話可能會出現

   Packet for query is too large (37748784 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable

 異常 這是能夠在

[mysqld]下面添加 max_allowed_packet=10M來擴大限制

在 jdk 6。0 之前 向數據庫插入clob 和blob數據的操做方法:

 void setBinaryStream(int parameterIndex, java.io.InputStream x, int length)方法

而在jdk 6.0之後就能夠用

void setClob(int parameterIndex, Reader reader)

void setBlob(int parameterIndex, InputStream inputStream)方法來插入clob/blob

讀取時候能夠用讀取流來處理或者用:

clob的時候能夠

用 Clob.getSubString(pos, length)不過length是個int型的

或者用

Java代碼 

Clob c = rs.getClob("clumn");  
StringBuffer a = new StringBuffer(1024);  
Reader r = c.getCharacterStream();  
char[] cc = new char[1];  
int i = -1;  
while((i =r.read(cc))!=-1){  
    a.append(cc);  
}

 讀取blob能夠用:

Blob b = rs.getBlob("clumn");
java.io.InputStream getBinaryStream ()或者getBytes(pos, length)
相關文章
相關標籤/搜索