Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6923953
  • 博文数量: 700
  • 博客积分: 10821
  • 博客等级: 上将
  • 技术积分: 12011
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-02 10:41
个人简介

大数据、ML、AI、云计算openstack、Linux、SpringCloud。

文章分类

全部博文(700)

分类: Java

2014-05-16 10:27:12

该文只介绍了BLOB操作、稍后会有TEXT的操作文章。

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. java.lang.IllegalArgumentException: Packet is larger than max_allowed_packet from server configuration of 1048576 bytes  

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表。分表存储,能够显著提高查询速度。






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


向MySQL数据库插入Blob数据的问题

[摘要]:在使用Hibernate向数据库插入Blob二进制数据时,发生如下错误:SQL
Error: 1064, SQLState: 42000 。You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right syntax to use
near '??^5b??08""199G?"0Px8=?ü??Y??ó??l%P?[
¨???ó`-??F????:???S?a?@??Zu??' at
line
1
[关键字]:MySQL、Blob、图片、image、java、Hibernate、Clob、&
[环境]:5.1.34-community
MySQL Community Server (GPL),Hibernate 3.2.5
[作者]:Winty (wintys@gmail.com)
http://www.blogjava.net/wintys

[错误]:
   
使用Hibernate向数据库插入Blob二进制数据,程序如下:


    public void insert() {
  
     User user = new User();
  
     Transaction tc = null;
  
     try{
      
     Session session =
HibernateUtil.getSession();
      
     tc = session.beginTransaction();
  
         
      
     user.setName("The Name");
  
         
      
     FileInputStream fin = new
FileInputStream("rc/redheart.gif");
      
     Blob image = Hibernate.createBlob(fin);
  
       
 user.setImage(image);
      
     
          
 File file = new File("rc/news.txt");
      
     FileReader fr = new FileReader(file);
  
         BufferedReader br = new
BufferedReader(fr);
          
 Clob info = Hibernate.createClob(br , (int)file.length());
  
         user.setInfo(info);
  
         
      
     session.save(user);
      
     
          
 tc.commit();
        }catch(Exception
e){
            if(tc !=
null){
              
 tc.rollback();
          
 }
          
 System.err.println(e.getMessage());      
     
      
 }finally{
          
 HibernateUtil.closeSession();
      
 }
    }
    发生如下错误:

Hibernate: insert into db.myblobclob (name, image, info, id) values (?, ?,
?, ?)
00:33:45,671  WARN JDBCExceptionReporter:77 - SQL Error: 1064,
SQLState: 42000
00:33:45,671 ERROR JDBCExceptionReporter:78 - You have an
error in your SQL syntax; check the manual that corresponds to your MySQL server
version for the right syntax to use near
'??^5b??08""199G?"0Px8=?ü??Y??ó??l%P?[
¨???ó`-??F????:???S?a?@??Zu??' at line
1
00:33:45,687 ERROR AbstractFlushingEventListener:301 - Could not
synchronize database state with
session
org.hibernate.exception.SQLGrammarException: Could not execute JDBC
batch update
    at
org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
  
 at
org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
  
 at
org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
  
 at
org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237)
  
 at
org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
  
 at
org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
  
 at
org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
  
 at
org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
  
 at
org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
  
 at
org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
  
 at
wintys.hibernate.blobclob.UserDAOBean.insert(UserDAOBean.java:41)
  
 at wintys.hibernate.blobclob.UserTest.main(UserTest.java:18)
Caused by:
java.sql.BatchUpdateException: You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right syntax to use
near '??^5b??08""199G?"0Px8=?ü??Y??ó??l%P?[
¨???ó`-??F????:???S?a?@??Zu??' at
line 1
    at
com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1693)
  
 at
com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1108)
  
 at
org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
  
 at
org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
  
 ... 9 more
Could not execute JDBC batch update
Hibernate: select
user0_.id as id0_, user0_.name as name0_, user0_.image as image0_, user0_.info
as info0_ from db.myblobclob user0_

[原因]:
  
 搜索了一下,错误原因可能为:"在定义字段时,不要和MYSQL的保留字段有相同的"。
   
检查了一下表中的字段名,没有发现问题:

CREATE TABLE myblobclob(
   
id          VARCHAR(100) NOT
NULL,
    name   
VARCHAR(100),
    image  
BLOB,
    info      
TEXT,
    PRIMARY KEY(id)
);

  
 如果把Blob相关的程序注释了,Clob数据能够正常写入。原因当然出在Blob数据的写入程序中。后来发现,把Blob写入的图片数据换成文本,却可以正常写入。可见,是二进制数据的编码问题。

[解决]:
  
 将原来的数据连接:


  
 jdbc:mysql://localhost:3306/db

  
 修改成:


  
 

  
 注意,在将连接字符串放到CDATA中,因为&是XML中的转义字符。不然会提示错误:
    Error
parsing XML: /hibernate.cfg.xml(12) The reference to entity "characterEncoding"
must end with the ';' delimiter.

  
 也可以直接把&修改为&
    即:
  
 jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf-8
阅读(54576) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~