Java对象序列化存BLOB需实现Serializable接口并用ObjectOutputStream转字节数组,再通过PreparedStatement.setBytes()写入;反序列化用ResultSet.getBytes()配合ObjectInputStream还原,注意serialVersionUID、transient字段及异常处理。

Java 中将对象序列化后存入数据库 BLOB 字段,核心是:先用 ObjectOutputStream 将对象转为字节数组,再通过 JDBC 的 PreparedStatement.setBytes() 或 setBinaryStream() 写入 BLOB 字段。
确保对象可序列化
被存储的类必须实现 java.io.Serializable 接口,且所有非静态、非瞬态(transient)字段的类型也需可序列化:
- 推荐显式声明
private static final long serialVersionUID = 1L;,避免反序列化版本不兼容 - 含不可序列化字段(如 I/O 流、线程、数据库连接等)时,用
transient修饰跳过序列化 - 若使用 Lombok,加
@Data和implements Serializable即可,但仍需手动补serialVersionUID
序列化对象为字节数组
避免直接写文件流,应使用 ByteArrayOutputStream 获取原始字节:
public static byte[] serialize(Object obj) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(obj);
return bos.toByteArray();
}
}
- 不要用
ObjectOutputStream直接包装FileOutputStream后去读文件——BLOB 存储不需要中间文件 - 注意捕获
NotSerializableException,用于快速定位哪个字段未实现Serializable
写入数据库 BLOB 字段
以 MySQL / PostgreSQL / Oracle 等主流数据库为例,使用标准 JDBC 方式:
立即学习“Java免费学习笔记(深入)”;
String sql = "INSERT INTO user_cache (id, data) VALUES (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, "user_1001");
ps.setBytes(2, serialize(userObj)); // 直接传 byte[]
ps.executeUpdate();
}
- 多数 JDBC 驱动支持
setBytes(),简单可靠;大数据量时可用setBinaryStream(2, new ByteArrayInputStream(bytes)) - MySQL 中 BLOB 类型选
MEDIUMBLOB(最大 16MB)或LONGBLOB(4GB),避免用TINYBLOB导致截断 - Oracle 使用
BLOB类型,需配合oracle.sql.BLOB特殊处理(推荐优先用setBytes简化)
从 BLOB 反序列化还原对象
读取时用 ResultSet.getBytes() 拿字节数组,再用 ObjectInputStream 还原:
byte[] bytes = rs.getBytes("data");
if (bytes != null) {
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis)) {
User user = (User) ois.readObject();
}
}
- 务必检查
bytes是否为null,防止NullPointerException - 反序列化可能抛
ClassNotFoundException(类路径缺失)或InvalidClassException(serialVersionUID不匹配),建议日志中打印异常原因 - 生产环境慎用 Java 原生序列化——它脆弱、不跨语言、有安全风险;高并发或长期存储场景建议换 JSON(Jackson/Gson)或 Protocol Buffers
不复杂但容易忽略细节。关键在可序列化契约、字节数组流转、BLOB 容量匹配和反序列化异常兜底。


















