Java通过JDBC流式读写MySQL的TEXT/BLOB字段可防OOM,需选对类型(如LONGTEXT/MEDIUMBLOB)、用setCharacterStream/getCharacterStream或setBinaryStream/getBinaryStream,并调优maxAllowedPacket与fetchSize等配置。

Java 通过 JDBC 处理 MySQL 中的 TEXT 和 BLOB 字段,核心是避免整块加载、改用流式读写,防止内存溢出(OOM)。MySQL 本身不支持标准 JDBC 的 CLOB/BLOB 接口语义,而是用 TEXT 类型替代 CLOB、BLOB 类型替代 BLOB,JDBC 驱动通过 setCharacterStream/getCharacterStream(文本)和 setBinaryStream/getBinaryStream(二进制)来对接。
选对字段类型,匹配数据规模
字段类型选错会引发截断或性能浪费:
- 大文本(如协议、日志、富文本内容):小量用
TEXT(≤64KB),中等用MEDIUMTEXT(≤16MB),超大内容(如整本电子书)用LONGTEXT(≤4GB) - 二进制数据(如图片、PDF、音频):头像/文档附件常用
MEDIUMBLOB,原始视频或备份包才考虑LONGBLOB - 避免把 2MB 的 Markdown 文件存在
TEXT里——可能被截断;也别为 50KB 的 PNG 图片用LONGBLOB——徒增索引和复制开销
写入大文本:用 FileReader + setCharacterStream
不把整个文件读成 String,而是以字符流方式注入数据库:
- 准备
FileReader,注意长度参数是int类型,所以文件不能超过 2GB - 调用
pstmt.setCharacterStream(1, reader, (int) file.length()) - 执行前确保连接已关闭 auto-commit:
conn.setAutoCommit(false),写完手动commit(),尤其批量操作时 - SQL 示例:
INSERT INTO article (title, content) VALUES (?, ?),其中content是LONGTEXT
读取大文本:按需选择 getCharacterStream 或 getString
取决于处理方式和数据预期大小:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 用
rs.getCharacterStream("content")获取Reader:适合边读边处理,比如逐行解析日志、分块写入本地文件、流式转 JSON - 用
rs.getString("content"):仅限确认内容很小(如短评论、配置片段),否则易触发 OOM - 无论哪种方式,读完必须显式关闭 Reader:
reader.close(),否则数据库连接资源可能泄漏
读写二进制数据:统一走 InputStream/OutputStream 流
原理与文本一致,但换用字节流接口:
- 写入时:
pstmt.setBinaryStream(1, new FileInputStream(file), (int) file.length()) - 读取时:
InputStream is = rs.getBinaryStream("attachment"),再配合Files.copy(is, Paths.get("out.pdf"))保存到磁盘 - 关键配置:MySQL 默认
maxAllowedPacket=4MB,存大文件需在 JDBC URL 中加大,例如:?maxAllowedPacket=67108864(64MB) - 读取时建议套
BufferedInputStream,提升吞吐;写入目标文件也推荐用BufferedOutputStream
查询时的配套优化
光靠流式方法还不够,驱动行为也要调优:
- 查询前设置
statement.setFetchSize(Integer.MIN_VALUE),启用 MySQL Connector/J 的流式游标(逐行获取,不缓存整结果集) - 连接 URL 加参数:
?useServerPrepStmts=false&cachePrepStmts=false&tinyInt1isBit=false,避免某些版本下流式读取被意外禁用 - 禁用 auto-commit 不仅适用于写入,读取大字段时也建议保持事务关闭状态,减少驱动内部缓存压力

















