当前位置: 首页 > news >正文

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)。
  • 事务管理

    • 大文件操作建议在事务中执行,确保数据一致性。
    • 插入和读取操作需在同一个事务中完成(示例中已关闭自动提交)。
  • 异常处理

    • 捕获 SQLExceptionIOException,确保资源正确释放。
  • 数据库兼容性

    • 不同数据库的 BLOB/CLOB 类型可能不同(如 Oracle 的 BLOBCLOB,MySQL 的 LONGBLOBLONGTEXT)。

运行前准备

  1. 依赖:确保项目包含 MySQL JDBC 驱动(如 mysql-connector-java)。
  2. 文件路径
    • blobFilePath:替换为实际二进制文件路径(如 D:/test_image.jpg)。
    • clobFilePath:替换为实际文本文件路径(如 D:/large_text.txt)。

示例输出

BLOB 文件已保存!
CLOB 文件已保存!
操作成功,事务已提交!

扩展建议

  • 分块读取优化
    对于超大文件,可调整缓冲区大小(如 8192)或使用 ResultSet 的流式处理(getBinaryStream() 直接写入文件)。

  • 性能优化

    • 使用 setBlob()setClob() 方法,直接传递 InputStreamReader,避免内存缓存。
  • 安全性
    确保文件路径权限正确,防止越权访问。

通过此示例,你可以实现对大文件的高效存储和读取,适用于图片、文档等二进制数据或长文本的存储场景。

相关文章:

  • RocketMQ面试题:基础部分
  • G-Star 校园开发者计划·黑科大|开源第一课之 Git 入门
  • 简易shell
  • Python深浅拷贝
  • mysql 查询进程查看并释放
  • 存储过程在高并发环境下的重要性
  • await func().catch()和try{ func() }.catch(),两种写法,有什么区别
  • 设计模式之工厂模式的优缺点
  • NLP 与常见的nlp应用
  • AI在工业自动化中的应用与挑战
  • 麦科信新品发布,8MHz,300Arms高频交直流电流探头CP3008
  • Linux驱动开发实战之SRIO驱动(二)基于Tsi721驱动
  • 分布式中间件:RabbitMQ确认消费机制
  • QT网页显示的几种方法及对比
  • 计算机网络精讲day1——计算机网络的性能指标(上)
  • 【大坐标处理】
  • MyBatis plus详解
  • 使用BootStrap 3的原创的模态框组件,没法弹出!估计是原创的bug
  • day-110 下降路径最小和 II
  • filebeat和logstash区别
  • 绿城房地产集团:近半年累计花费20.6亿元购买旗下债券
  • 吴勇强、高颜已任南京市委常委
  • 法治日报:商品明细是隐私,外卖员快递员不应知晓
  • 宁波市人大常委会审议生育工作报告,委员建议学前教育免费
  • 十四届全国政协原常委、民族和宗教委员会原副主任苟仲文被提起公诉
  • 商务部新闻发言人就中美经贸高层会谈答记者问