了解1 操作BLOB类型字段
1.MySQL BLOB类型
MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。
实际使用中根据需要存入的数据大小定义不同的BLOB类型。
需要注意的是:如果存储的文件过大,数据库的性能会下降。
如果在指定了相关的Blob类型以后,还报错:xxx too large,(如Blob类型为MediumBlob,本来最大能存16M,结果存了2M的图片,却报错,因为mysql数据库配置中默认允许最大是1M)那么在mysql的安装目录下,找my.ini文件加上如下的配置参数: max_allowed_packet=16M。同时注意:修改了my.ini文件之后,需要重新启动mysql服务。(MYSQL8默max_allowed_packet=64M)
2.操作Blob类型的数据
使用PrepareStatement操作Blob类型的数据(向表中插入图片)
插入的图片大小不能大于表中photo字段的类型最大容量,否则会报错。
public class BlobTest {
public static void main(String[] args) {
testInsert();
}
//向customer表中插入Blob类型的字段(插图片)
public static void testInsert() {
Connection getconnection = null;
PreparedStatement preparedStatement = null;
try {
getconnection = JDBCUtills.getconnection();
String sql = " insert into customers(name,email,birth,photo) values (?,?,?,?)";
preparedStatement = getconnection.prepareStatement(sql);
preparedStatement.setObject(1, "张宇");
preparedStatement.setObject(2, "zhang@qq.com");
preparedStatement.setObject(3, "1999-09-26");
//Blob类型的数据一般以文件的方式传送,不单纯是一个变量
FileInputStream is = new FileInputStream("1.jpg");
preparedStatement.setBlob(4, is);
preparedStatement.execute();
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
JDBCUtills.closeconnection(getconnection, preparedStatement);
}
}
}
使用PrepareStatement操作Blob类型的数据(读取表中图片并下载到本地)
public class BlobTest2 {
public static void main(String[] args) {
testQuery();
}
public static void testQuery() {
Connection getconnection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
InputStream is = null;
FileOutputStream fileOutputStream = null;
try {
//查询customers表中Blob类型字段
getconnection = JDBCUtills.getconnection();
String sql = "select id,name,email,birth,photo from customers where id = ?";
preparedStatement = getconnection.prepareStatement(sql);
preparedStatement.setObject(1, 32);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
//方式1
// int id = resultSet.getInt(1);
// String name = resultSet.getString(2);
// String email= resultSet.getString(3);
// Date birth = resultSet.getDate(4);
//方式2
int id = resultSet.getInt("id");//形参是列的别名
String name = resultSet.getString("name");
String email = resultSet.getString("email");
Date birth = resultSet.getDate("birth");
//将Blob类型的字段下载下来,以文件的方式保存到本地
Blob photo = resultSet.getBlob("photo");
is = photo.getBinaryStream();//得到图片的输入流
//将文件下载到本地
fileOutputStream = new FileOutputStream("3.jpg");
byte[] bytes = new byte[1024];
int len;记录每次读取的字节的个数
//读取输入流
while ((len = is.read(bytes)) != -1) {//返回读入的一个字节。如果达到文件末尾,返回-1
fileOutputStream.write(bytes, 0, len); //每次写出len个字符
}
Customers customers = new Customers(id, name, email, birth);
System.out.println(customers);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源 (包括输入流 输出流)
try {
if (is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fileOutputStream != null)
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
JDBCUtills.closeconnection(getconnection, preparedStatement, resultSet);
}
}
}
重点2 批量插入
当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率
JDBC的批量处理语句包括下面三个方法:
addBatch(String):添加需要批量处理的SQL语句或是参数;
executeBatch():执行批量处理语句;
clearBatch():清空缓存的数据
举例:向数据表中插入20000条数据
数据库中提供一个goods表。创建如下:
CREATE TABLE goods(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);
实现层次一:使用Statement
//了解
Connection conn = JDBCUtils.getConnection();
Statement st = conn.createStatement();
for(int i = 1;i <= 20000;i++){
String sql = "insert into goods(name) values('name_' + "+ i +")";
st.executeUpdate(sql);
}
实现层次二:使用PreparedStatement
public class ManyData {
public static void main(String[] args) {
testInsert1();
}
public static void testInsert1() {
Connection getconnection = null;
PreparedStatement preparedStatement = null;
try {
long start = System.currentTimeMillis();
getconnection = JDBCUtills.getconnection();
String sql = "insert into goods (name) values (?)";
preparedStatement = getconnection.prepareStatement(sql);
//批量插入
for (int i = 0; i < 20000; i++) {
preparedStatement.setObject(1, "name_" + i);
preparedStatement.execute();
}
long end = System.currentTimeMillis();
System.out.println("花费的时间为" + (end - start));//花费的时间为42889
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JDBCUtills.closeconnection(getconnection, preparedStatement);
}
}
}
实现层次三 Batch
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Insert {
public static void main(String[] args) {
testInsert1();
}
public static void testInsert1() {
/*
* 修改1: 使用 addBatch() / executeBatch() / clearBatch()
* 修改2:mysql服务器默认是关闭批处理的,不能使用Batch,我们需要通过一个参数,让mysql开启批处理的支持。
* &rewriteBatchedStatements=true 写在配置文件的url后面
* 修改3:使用更新的mysql 驱动:mysql-connector-java-8.0.28-bin.jar
*
*/
Connection getconnection = null;
PreparedStatement preparedStatement = null;
try {
long start = System.currentTimeMillis();
getconnection = JDBCUtills.getconnection();
String sql = "insert into goods (name) values (?)";
preparedStatement = getconnection.prepareStatement(sql);
for (int i = 1; i <= 20000; i++) {
preparedStatement.setObject(1, "name_" + i);
//每隔500次执行一批sql语句
//1. 攒sql
preparedStatement.addBatch();
if (i % 500 == 0) {
//2.执行一次
preparedStatement.executeBatch();
//3.清空Batch
preparedStatement.clearBatch();
}
}
long end = System.currentTimeMillis();
System.out.println("花费的时间为" + (end - start));//花费的时间为2858
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JDBCUtills.closeconnection(getconnection, preparedStatement);
}
}
}
实现层次四(终极版)
使用Connection 的 setAutoCommit(false) / commit()
public class InsertTest2 {
public static void main(String[] args) {
testInsert1();
}
public static void testInsert1() {
/*
* 修改1: 使用 addBatch() / executeBatch() / clearBatch()
* 修改2:mysql服务器默认是关闭批处理的,不能使用Batch,我们需要通过一个参数,让mysql开启批处理的支持。
* ?rewriteBatchedStatements=true 写在配置文件的url后面
* 修改3:使用更新的mysql 驱动:mysql-connector-java-5.1.37-bin.jar
*
*/
Connection getconnection = null;
PreparedStatement preparedStatement = null;
try {
long start = System.currentTimeMillis();
getconnection = JDBCUtills.getconnection();//获取数据库连接
//设置不允许自动提交数据
getconnection.setAutoCommit(false);
String sql = "insert into goods (name) values (?)";
preparedStatement = getconnection.prepareStatement(sql);
for (int i = 1; i <= 20000; i++) {
preparedStatement.setObject(1, "name_" + i);
//每隔500次执行一批sql语句
//1. 攒sql
preparedStatement.addBatch();
if (i % 500 == 0) {
//2.执行一次
preparedStatement.executeBatch();//默认提交数据,每提交一次数据到数据库中,及写死在数据库中,也需要花费时间
//3.清空Batch
preparedStatement.clearBatch();
}
}
//提交数据