MySQL 中的Blog杂谈

[color=red][b]声明:本人完全copy来的[/b][/color]
一、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";
问题解决了,不仅能支持各种格式的文件,图片也显示正常了。如果设置为其他的字符集就会出现前面的错误。



四、max_allowed_packet参数设置

往数据库中存储较大的文件是出现如下错误:



Java代码
1.[b]java.lang.IllegalArgumentException: Packet is larger than max_allowed_packet from server configuration of 1048576 bytes[/b]
这是因为存入的文件大于mysql默认的 max_allowed_packet值。

解决办法:在mysql安装目录下的my.ini文件中的最后一行添加

Java代码
1.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写入的图片数据换成文本,却可以正常写入。可见,是二进制数据的编码问题。

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

<property name="connection.url">
jdbc:mysql://localhost:3306/db
</property>

修改成:

<property name="connection.url">
<![CDATA[jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf-8]]>
</property>

注意,在将连接字符串放到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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值