JDBC 操作 BLOB(二进制大对象)和 CLOB(字符大对象)的完整示例代码,包含 插入、读取 操作及详细注释
以下是使用 JDBC 操作 BLOB(二进制大对象)和 CLOB(字符大对象) 的完整示例代码,包含 插入、读取 操作及详细注释:
1. 数据库表结构(MySQL 示例)
CREATE TABLE files (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
content BLOB, -- 存储二进制文件(如图片、PDF)
text_content CLOB -- 存储大文本(如长文章)
);
2. Java 代码示例
import java.io.*;
import java.sql.*;
public class BlobClobExample {
// 数据库连接参数
private static final String URL = "jdbc:mysql://localhost:3306/mydatabase";
private static final String USER = "root";
private static final String PASSWORD = "your_password";
public static void main(String[] args) {
Connection conn = null;
try {
// 1. 加载驱动并获取连接
conn = DriverManager.getConnection(URL, USER, PASSWORD);
conn.setAutoCommit(false); // 关闭自动提交,启用事务
// 2. 插入 BLOB 和 CLOB 数据
insertBlobAndClob(conn, "test_image.jpg", "large_text.txt");
// 3. 查询并读取 BLOB 和 CLOB 数据
readBlobAndClob(conn, 1);
// 4. 提交事务
conn.commit();
System.out.println("操作成功,事务已提交!");
} catch (SQLException e) {
System.out.println("发生异常,事务回滚!");
try {
if (conn != null) conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
} finally {
try {
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// ------------------------ 插入 BLOB 和 CLOB 数据 ------------------------
private static void insertBlobAndClob(Connection conn, String blobFilePath, String clobFilePath) throws SQLException, IOException {
// SQL 语句
String sql = "INSERT INTO files (name, content, text_content) VALUES (?, ?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 设置 name 参数
pstmt.setString(1, "Sample File");
// 设置 BLOB 参数(二进制文件)
try (FileInputStream fis = new FileInputStream(blobFilePath)) {
pstmt.setBinaryStream(2, fis, (int) new File(blobFilePath).length());
}
// 设置 CLOB 参数(文本文件)
try (FileReader fr = new FileReader(clobFilePath)) {
pstmt.setCharacterStream(3, fr, (int) new File(clobFilePath).length());
}
pstmt.executeUpdate();
}
}
// ------------------------ 读取 BLOB 和 CLOB 数据 ------------------------
private static void readBlobAndClob(Connection conn, int id) throws SQLException, IOException {
// SQL 语句
String sql = "SELECT name, content, text_content FROM files WHERE id = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, id);
try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
String name = rs.getString("name");
Blob blob = rs.getBlob("content");
Clob clob = rs.getClob("text_content");
// 保存 BLOB 到文件
saveBlobToFile(blob, "output_image.jpg");
System.out.println("BLOB 文件已保存!");
// 保存 CLOB 到文件
saveClobToFile(clob, "output_text.txt");
System.out.println("CLOB 文件已保存!");
}
}
}
}
// ------------------------ 辅助方法 ------------------------
// 将 Blob 保存为文件
private static void saveBlobToFile(Blob blob, String outputFilePath) throws SQLException, IOException {
try (InputStream is = blob.getBinaryStream();
FileOutputStream fos = new FileOutputStream(outputFilePath)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
}
}
// 将 Clob 保存为文件
private static void saveClobToFile(Clob clob, String outputFilePath) throws SQLException, IOException {
try (Reader reader = clob.getCharacterStream();
FileWriter fw = new FileWriter(outputFilePath)) {
char[] buffer = new char[4096];
int bytesRead;
while ((bytesRead = reader.read(buffer)) != -1) {
fw.write(buffer, 0, bytesRead);
}
}
}
}
代码说明
1. 插入数据(BLOB 和 CLOB)
-
BLOB 操作:
- 使用
FileInputStream
读取本地文件。 - 通过
setBinaryStream()
将输入流传递给PreparedStatement
。 - 参数
2
对应 SQL 中的?
占位符(第二个参数)。
- 使用
-
CLOB 操作:
- 使用
FileReader
读取文本文件。 - 通过
setCharacterStream()
将字符流传递给PreparedStatement
。
- 使用
2. 读取数据(BLOB 和 CLOB)
-
BLOB 读取:
- 通过
getBlob("content")
获取Blob
对象。 - 使用
getBinaryStream()
获取输入流,逐块读取并写入目标文件。
- 通过
-
CLOB 读取:
- 通过
getClob("text_content")
获取Clob
对象。 - 使用
getCharacterStream()
获取字符流,逐块读取并写入目标文件。
- 通过
3. 关键注意事项
-
流操作:
- 使用缓冲区(
byte[]
或char[]
)逐块读写,避免内存不足。 - 确保所有流在使用后关闭(通过
try-with-resources
)。
- 使用缓冲区(
-
事务管理:
- 大文件操作建议在事务中执行,确保数据一致性。
- 插入和读取操作需在同一个事务中完成(示例中已关闭自动提交)。
-
异常处理:
- 捕获
SQLException
和IOException
,确保资源正确释放。
- 捕获
-
数据库兼容性:
- 不同数据库的 BLOB/CLOB 类型可能不同(如 Oracle 的
BLOB
和CLOB
,MySQL 的LONGBLOB
和LONGTEXT
)。
- 不同数据库的 BLOB/CLOB 类型可能不同(如 Oracle 的
运行前准备
- 依赖:确保项目包含 MySQL JDBC 驱动(如
mysql-connector-java
)。 - 文件路径:
blobFilePath
:替换为实际二进制文件路径(如D:/test_image.jpg
)。clobFilePath
:替换为实际文本文件路径(如D:/large_text.txt
)。
示例输出
BLOB 文件已保存!
CLOB 文件已保存!
操作成功,事务已提交!
扩展建议
-
分块读取优化:
对于超大文件,可调整缓冲区大小(如8192
)或使用ResultSet
的流式处理(getBinaryStream()
直接写入文件)。 -
性能优化:
- 使用
setBlob()
和setClob()
方法,直接传递InputStream
或Reader
,避免内存缓存。
- 使用
-
安全性:
确保文件路径权限正确,防止越权访问。
通过此示例,你可以实现对大文件的高效存储和读取,适用于图片、文档等二进制数据或长文本的存储场景。