java jdbc 处理 clob/blob 的核心是全程流式操作:写入用 setcharacterstream/setbinarystream 或 setclob/setblob,读取用 getcharacterstream/getbinarystream,严禁 getstring()/getbytes()/tostring() 全量加载,否则易触发 outofmemoryerror。

Java 中用 JDBC 处理大文本(如 MySQL 的 LONGTEXT)和二进制字段(如 LONGBLOB),关键不是“能不能存”,而是“怎么避免内存炸掉”。核心就一条:全程走流,不拼字符串、不转字节数组、不调 getString() 或 getBytes()。
写入大文本(LONGTEXT / CLOB 类型)
不能用 pstmt.setString(),尤其含中文时——整段文本会先加载进内存再编码,超 10MB 就容易 OOM。
- 推荐方式:
pstmt.setCharacterStream(参数索引, reader, 长度),例如传new FileReader(file),长度可传(int) file.length()或 -1(JDBC 4.0+ 自动推断) - 语义更清晰的写法:
pstmt.setClob(参数索引, reader),底层仍是流式,适合团队协作时明确意图 - 如果内容纯 ASCII(极少场景),可用
setAsciiStream();但日常项目一律按 Unicode 处理,优先选setCharacterStream
写入二进制文件(LONGBLOB / BLOB 类型)
严禁用 pstmt.setBytes(byte[]) 或 pstmt.setBlob(byte[])——哪怕一个 50MB 的图片,也会瞬间占满 JVM 堆。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 最简可靠:
pstmt.setBinaryStream(参数索引, inputStream, length),例如new FileInputStream(file) - 需要复用或分块写入时:先
conn.createBlob()创建空 Blob,再用blob.setBinaryStream(1)获取输出流写入,最后pstmt.setBlob(参数索引, blob) - Oracle 等老数据库需两阶段:先插
empty_blob()占位,再SELECT ... FOR UPDATE获取定位器写入;MySQL/PostgreSQL 一般支持直写
读取大文本字段
别碰 rs.getString("content")——TypeHandler 会强制把全部内容读成 String,风险极高。
- 标准流程:
Clob clob = rs.getClob("content"); Reader r = clob.getCharacterStream();,然后用BufferedReader.readLine()或循环r.read(char[])按需读取 - 仅当确认内容极小(比如日志摘要前 1KB)且可控时,才用
clob.getSubString(1, (int) clob.length()) - 绝对避免
clob.toString()、clob.getAsciiStream().readAllBytes()这类全量加载操作
读取二进制字段
rs.getBytes() 是 OOM 元凶之一,必须绕开。
- 正确姿势:
Blob blob = rs.getBlob("photo"); InputStream is = blob.getBinaryStream();,后续可直接传给ImageIO.read(is)、写入磁盘文件,或用IOUtils.copy(is, os)流式转发 - 小文件(如头像、图标)且确定不超过几 MB,才考虑
blob.getBytes(1, (int) blob.length()) - 所有流(Reader / InputStream / OutputStream)必须用 try-with-resources 或手动 close,否则连接和文件句柄泄漏风险高
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










