四:操作BLOB类型字段
1.MySQL BLOB类型
-
在MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。可以用来存储图片,视频等
-
插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。
-
MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)
-
实际使用中根据需要存入的数据大小定义不同的BLOB类型。
-
如果在指定了相关的Blob类型以后,还报错:xxx too large,那么在mysql的安装目录下,找
my.ini
文件加上如下的配置参数: max_allowed_packet=16M。同时注意:修改了my.ini文件之后,需要重新启动mysql服务。
2.向数据表customer中插入Blob类型的字段
public class BlobTest {
@Test
public void testInsert() throws Exception {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBC_Utils.getConnection();
String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";
ps = conn.prepareStatement(sql);
ps.setObject(1, "张杰");
ps.setObject(2, "ZhangJie@168.com");
ps.setObject(3, "1992-09-08");
FileInputStream is = new FileInputStream(new File("zhangjie.jpg"));
//如果文件大于1MB,可能会报xxx too large错误,解决方法参照上面的解决方式
ps.setBlob(4, is);
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBC_Utils.closeResource(conn, ps);
}
}
}
注:在工作目录下要有zhangjie.jpg
,否则会提示找不到文件
3.查询数据表customer中的Blob字段
@Test
public void testQuery(){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
InputStream is = null;
FileOutputStream fos = null;
try {
conn = JDBC_Utils.getConnection();
String sql = "select id,name,email,birth,photo from customers where id = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1,21);
rs = ps.executeQuery();
if(rs.next()) {
//使用列的别名来查找
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
Date birth = rs.getDate("birth");
Customer customer = new Customer(id,name,email,birth);
System.out.println(customer);
//将Blob类型的字段下载下来,以文件的形式保留到本地
Blob photo = rs.getBlob("photo");
is = photo.getBinaryStream();
fos = new FileOutputStream("singer.jpg");
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
JDBC_Utils.closeResource(conn, ps, rs);
}
}
五:批量插入
1.批量操作
当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率
JDBC的批量处理语句包括下面三个方法:
- addBatch(String):添加需要批量处理的SQL语句或是参数;
- executeBatch():执行批量处理语句;
- clearBatch():清空缓存的数据
通常我们会遇到两种批量执行SQL语句的情况:
- 多条SQL语句的批量处理;
- 一个SQL语句的批量传参;
2.高效的批量插入
- 使用
PreparedStatement
实现批量数据操作 update,delete
本身就具有批量操作的效果- 此时的批量操作,主要指批量插入
例: 题目向goods表添加100万条数据
CREATE TABLE goods(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(25)
);
import java.sql.Connection;
import java.sql.PreparedStatement;
import org.junit.Test;
import com.jdbc.util.JDBC_Utils;
public class InsertTest {
//方式一:使用Statement批量插入数据(略)
//方式二:使用PreparedStatement批量插入数据
@Test
public void testInsert1() {
Connection conn = null;
PreparedStatement ps = null;
try {
long start = System.currentTimeMillis();
conn = JDBC_Utils.getConnection();
String sql = "insert into goods(name)values(?)";
ps = conn.prepareStatement(sql);
for(int i = 1;i <= 1000000;i++) {
ps.setObject(1,"name_" + i);
ps.execute();
}
long end = System.currentTimeMillis();
System.out.println("插入花费时间为:" + (end - start) + "毫秒");//1350941毫秒---8473毫秒---5857毫秒
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBC_Utils.closeResource(conn, ps);
}
}
}
方式三:使用addBatch(),executeBatch(),clearBatch()
批量插入数据
-
mysql服务器默认关闭批处理,需要通过在url后添加?rewriteBatchedStatements=true来进行开启,不是mysqld的配置文件,是数据库连接的配置文件,即
jdbc.properties
-
mysql驱动需要5.1.37及以上版本
@Test public void testInsert2() { Connection conn = null; PreparedStatement ps = null; try { long start = System.currentTimeMillis(); conn = JDBC_Utils.getConnection(); String sql = "insert into goods(name)values(?)"; ps = conn.prepareStatement(sql); for(int i = 1;i <= 1000000;i++) { ps.setObject(1,"name_" + i); //1."攒"SQL ps.addBatch(); if(i % 500 == 0) { //2.执行batch ps.executeBatch(); //3.清空batch ps.clearBatch(); } } long end = System.currentTimeMillis(); System.out.println("插入花费时间为:" + (end - start) + "毫秒"); } catch (Exception e) { e.printStackTrace(); }finally { JDBC_Utils.closeResource(conn, ps); } }
方式四:设置连接不允许自动提交数据
@Test
public void testInsert3() {
Connection conn = null;
PreparedStatement ps = null;
try {
long start = System.currentTimeMillis();
conn = JDBC_Utils.getConnection();
//设置不允许自动提交,默认执行SQL,就自动提交到数据库
conn.setAutoCommit(false);
String sql = "insert into goods(name)values(?)";
ps = conn.prepareStatement(sql);
for(int i = 1;i <= 1000000;i++) {
ps.setObject(1,"name_" + i);
//1."攒"SQL
ps.addBatch();
if(i % 500 == 0) {
//2.执行batch
ps.executeBatch();
//3.清空batch
ps.clearBatch();
}
}
//提交数据
conn.commit();
long end = System.currentTimeMillis();
System.out.println("插入花费时间为:" + (end - start) + "毫秒");
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBC_Utils.closeResource(conn, ps);
}
}
其中可能会出现不少的小问题,请多多包含
感谢大家的支持,关注,评论,点赞!
参考资料:尚硅谷_宋红康_JDBC核心技术