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

Java JDBC 处理 CLOB 和 BLOB 的核心原则是:全程流式操作,避开字符串或字节数组全量加载,否则极易触发 OutOfMemoryError。关键不在“能不能存取”,而在于“是否绕过了内存陷阱”。
写入 CLOB(长文本)必须用字符流
不能用 pstmt.setString(),尤其含中文时——这会把整个文本塞进内存再转码,一超限就崩。
- 推荐方式:
pstmt.setCharacterStream(paramIndex, reader, length),传入FileReader或StringReader,length 可传文件长度或 -1(JDBC 4.0+ 自动推断) - 兼容写法:
pstmt.setClob(paramIndex, reader),语义更清晰,底层仍走流 - 纯 ASCII 场景可用
setAsciiStream(),但实际项目中几乎不用,Unicode 支持才是常态
写入 BLOB(二进制文件)必须用输入流
不能用 pstmt.setBytes() 或直接传 byte[],大文件瞬间吃光堆内存。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 最简可靠:
pstmt.setBinaryStream(paramIndex, inputStream, length),例如new FileInputStream(file) - Oracle 等老库需分两步:先插
empty_blob()占位,再SELECT ... FOR UPDATE获取定位器写入;MySQL 通常支持直写 - 若需分块写或复用 Blob 对象,可调
conn.createBlob()创建空 Blob,用blob.setBinaryStream(1)获取输出流写入,再pstmt.setBlob()
读取 CLOB 要拿 Reader,别 toString()
rs.getString("col") 看似方便,实为高危操作——TypeHandler 会强制加载全部内容到 String。
- 正确姿势:
Clob clob = rs.getClob("content"); Reader r = clob.getCharacterStream();,然后按需读取(如BufferedReader.readLine()或循环read(char[])) - 仅当确认内容很小(如日志前 1KB)且可控时,才用
clob.getSubString(1, (int) clob.length()) - 绝对避免
clob.toString()或clob.getAsciiStream().readAllBytes()这类全量加载调用
读取 BLOB 要拿 InputStream,别 getBytes()
和 CLOB 同理,rs.getBytes() 是 OOM 元凶之一。
- 标准流程:
Blob blob = rs.getBlob("photo"); InputStream is = blob.getBinaryStream();,后续可写入文件、解码图片(如ImageIO.read(is))、或用IOUtils.copy(is, os)流式转发 - 小文件(blob.getBytes(1, (int) blob.length())
- 注意资源释放:Reader/InputStream 必须在 try-with-resources 或 finally 中 close,否则连接池可能泄漏 LOB 定位器
数据库字段类型要匹配:MySQL 用 LONGTEXT/LONGBLOB,Oracle 用 CLOB/BLOB,PostgreSQL 注意 bytea 与 pg_largeobject 差异。只要坚持“实体字段用 java.sql.Clob/Blob + PreparedStatement 流式设参 + ResultSet 流式取流”,就能跨库稳定避坑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










