一、MySQL 的 BLOB 类型
MySQL 中,BLOB 是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
插入 BLOB 类型的数据必须使用 PreparedStatement,因为 BLOB 类型的数据无法使用字符串拼接写的。
MySQL 的四种BLOB类型(除了在存储的最大信息量不同外,他们是等同的)
实际使用中根据需要存入的数据大小定义不同的 BLOB 类型。
需要注意的是:如果存储的文件过大,数据库的性能会下降。
如果在指定了相关的 BLOB 类型以后,还报错:xxx too large,那么在MySQL的安装目录下,找 my.ini 文件加上如下的配置参数:
max_allowed_packet=16M
同时注意:修改了 my.ini 文件之后,需要重新启动 mysql 服务。
二、向表中插入大数据类型
代码测试:
1 @Test
2 public void testInsert1(){
3 Connection conn = null;
4 PreparedStatement ps = null;
5 FileInputStream fis = null;
6 try {
7 //获取连接
8 conn = JDBCUtils.getConnection();
9
10 String sql = "insert into customers(name, email, birth, photo) values(?, ?, ?, ?);";
11 ps = conn.prepareStatement(sql);
12
13
14 //填充占位符
15 ps.setString(1, "张三");
16 ps.setString(2, "zhangsan@126.com");
17 ps.setDate(3, new Date(new java.util.Date().getDay()));
18
19 //操作 blob 类型的变量
20 fis = new FileInputStream(new File("a.png"));
21 //ps.setBlob(4, fis);
22 ps.setBinaryStream(4, fis);
23
24 //执行
25 int i = ps.executeUpdate();
26 if (i > 0) {
27 System.out.println("执行成功");
28 }
29 } catch (Exception e) {
30 e.printStackTrace();
31 } finally {
32
33 try {
34 if (fis != null) {
35 fis.close();
36 }
37 } catch (IOException e) {
38 e.printStackTrace();
39 }
40 JDBCUtils.closeResource(conn, ps);
41 }
42
43 }
执行结果:
PreparedStatement 对象提供了两种方法来设置 BLOB 类型:
void setBlob(int parameterIndex, InputStream inputStream) throws SQLException;
void setBinaryStream(int parameterIndex, java.io.InputStream x) throws SQLException;
可以使用者两种方法来设置 BLOB 类型。
三、修改数据表中的Blob类型字段
修改的操作和插入的操作基本类似,代码示例如下:
1 @Test
2 public void testUpdate(){
3 Connection conn = null;
4 PreparedStatement ps = null;
5 FileInputStream fis = null;
6 try {
7 //获取连接
8 conn = JDBCUtils.getConnection();
9
10 String sql = "update customers set photo = ? where id = ?;";
11 ps = conn.prepareStatement(sql);
12
13
14 //填充占位符
15 //操作 blob 类型的变量
16 fis = new FileInputStream(new File("d.png"));
17 ps.setBlob(1, fis);
18
19 ps.setInt(2, 20);
20
21 //执行
22 boolean execute = ps.execute();
23 System.out.println("execute = " + execute);
24 if (execute) {
25 System.out.println("执行成功");
26 }
27 } catch (Exception e) {
28 e.printStackTrace();
29 } finally {
30
31 try {
32 if (fis != null) {
33 fis.close();
34 }
35 } catch (IOException e) {
36 e.printStackTrace();
37 }
38 JDBCUtils.closeResource(conn, ps);
39 }
40
41 }
四、从数据表中读取大数据类型
从数据库中读取 BLOB 类型数据:
1 @Test
2 public void testQuery(){
3 Connection conn = null;
4 PreparedStatement ps = null;
5 InputStream is = null;
6 FileOutputStream fos = null;
7 ResultSet rs = null;
8 try {
9 conn = JDBCUtils.getConnection();
10 String sql = "select id, name, email, birth, photo from customers where id = ?";
11 ps = conn.prepareStatement(sql);
12 ps.setInt(1, 20);
13 rs = ps.executeQuery();
14 if(rs.next()){
15 //方式一:
16 //int id = rs.getInt(1);
17 //String name = rs.getString(2);
18 //String email = rs.getString(3);
19 //Date birth = rs.getDate(4);
20
21 //方式二:
22 int id = rs.getInt("id");
23 String name = rs.getString("name");
24 String email = rs.getString("email");
25 Date birth = rs.getDate("birth");
26
27 Customer cust = new Customer(id, name, email, birth);
28 System.out.println(cust);
29
30 //将Blob类型的字段下载下来,以文件的方式保存在本地
31 //Blob photo = rs.getBlob("photo");
32 //is = photo.getBinaryStream();
33
34 is = rs.getBinaryStream("photo");
35 fos = new FileOutputStream("b1.jpg");
36 byte[] buffer = new byte[1024];
37 int len;
38 while((len = is.read(buffer)) != -1){
39 fos.write(buffer, 0, len);
40 }
41
42 }
43 } catch (Exception e) {
44 e.printStackTrace();
45 }finally{
46
47 try {
48 if(is != null)
49 is.close();
50 } catch (IOException e) {
51 e.printStackTrace();
52 }
53
54 try {
55 if(fos != null)
56 fos.close();
57 } catch (IOException e) {
58 e.printStackTrace();
59 }
60
61 JDBCUtils.closeResource(conn, ps, rs);
62 }
63
64 }
PreparedStatement 对象提供了两种方法来获取 BLOB 数据:
Blob getBlob(String columnLabel) throws SQLException;
java.io.InputStream getBinaryStream(String columnLabel) throws SQLException;
五、可能遇到的问题
当我们插入的图片过大时,可能会报下面的错误,这个时候我们就需要服务器端的 my.ini 配置文件中设置 max_allowed_packet = 16,然后需要重启服务。