mybatis处理blob/clob字段的关键是禁用默认全量加载:实体字段须声明为java.sql.clob/blob,mapper中显式配置jdbctype与javatype,业务层调用getcharacterstream()或getbinarystream()流式读取,避免tostring()或getbytes()触发oom。

MyBatis 处理 BLOB 和 CLOB 字段,关键不在“能不能读”,而在于“怎么读才不崩”。默认方式(如用 String 接 CLOB、byte[] 接 BLOB)极易触发 OutOfMemoryError——不是数据太大,是 TypeHandler 把整段内容一次性加载进内存。
明确字段映射类型,禁用默认全量加载
实体类字段必须声明为原生 JDBC 类型,而非字符串或字节数组:
- CLOB 字段 → 实体中定义为
java.sql.Clob - BLOB 字段 → 实体中定义为
java.sql.Blob
Mapper XML 中不能只写 #{content} 或依赖自动映射,必须显式指定类型:
<result column="content" property="clobContent" jdbctype="CLOB" javatype="java.sql.Clob"></result>
同理,BLOB 写 jdbcType="BLOB" javaType="java.sql.Blob"。这样 MyBatis 才会跳过 ClobTypeHandler 和 ByteArrayTypeHandler 的全量转换逻辑。
业务层按需流式读取,不提前加载
拿到 Clob 或 Blob 对象后,不要调用 .toString() 或 .getBytes() —— 这些方法会强制加载全部内容。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 读 CLOB:用
clob.getCharacterStream()获取Reader,逐块读或直接复制到目标输出流 - 读 BLOB:用
blob.getBinaryStream()获取InputStream,配合IOUtils.copy()或自定义缓冲区消费
例如校验前 100 字符,只需:
try (Reader reader = clob.getCharacterStream()) {
char[] buf = new char[100];
int len = reader.read(buf);
String preview = new String(buf, 0, len);
}
写入大字段时避免反向陷阱
插入或更新时,若传入 String 或 byte[],MyBatis 默认仍可能触发全量写入(尤其 Oracle 驱动)。稳妥做法是:
- 用
Connection.createClob()/createBlob()创建空 LOB 对象 - 通过
clob.setCharacterStream(1)或blob.setBinaryStream(1)获取流,分块写入 - 再将该 LOB 对象设入参数(
#{clob, jdbcType=CLOB})
不推荐自定义 TypeHandler 封装流写逻辑——易引入线程安全和资源泄漏风险。
数据库与驱动差异要心里有数
MySQL 的 TEXT/LONGTEXT 和 BLOB/LONGBLOB 在 JDBC 层仍走 Clob/Blob 接口;Oracle 原生支持更完整;PostgreSQL 则需注意其 pg_largeobject 的特殊性。但无论哪种,只要坚持“实体用 java.sql.Xxx + 业务层流式操作”这一模式,就能跨库稳定避坑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










