開發中常聽「持久化對象」「序列化傳輸」,兩者頻被混用。本文從定義、目的、接口、場景四個維度劃清界限。
| 維度 | 持久化 | 序列化 |
|---|---|---|
| 核心目的 | 對象生存期超越進程生命周期(掉電不丟) | 對象在網絡/進程間傳輸、複製 |
| 時間維度 | 長期存儲(天/月/年) | 短暫傳輸(毫秒/秒級) |
| 存儲介質 | 數據庫、文件系統、NoSQL、磁帶 | 內存流、網絡套接字、文件 |
| 數據格式 | 關係表、文檔、鍵值、列族 | 二進制、JSON、XML、Protobuf |
| 核心接口 | save/load/exists (ORM: persist/merge/remove) | serialize/deserialize (writeObject/readObject) |
| 典型框架 | Hibernate, MyBatis, JPA, Spring Data | Java原生, Kryo, Protobuf, Jackson |
| 事務性 | 支持 ACID 事務 | 無事務概念 |
| 查詢能力 | 支持 SQL/JPQL/Criteria 查詢 | 不可查詢,需反序列化後在內存操作 |
將內存對象保存到非易失性存儲,使其在應用重啟、機器掉電後仍可恢復。本質是「內存 → 外存」的映射與同步。
interface PersistenceManager {
void save(Object entity); // 新建/更新
Object load(Object id); // 通過主鍵加載
boolean exists(Object id); // 存在性檢查
void delete(Object entity); // 刪除
List
將對象圖轉換為字節序列,用於傳輸或暫存。重點在於「對象圖 → 字節流」的編碼與解碼。
interface Serializer {
void serialize(OutputStream out, Object obj); // 對象 → 字節流
Object deserialize(InputStream in); // 字節流 → 對象}
| 格式 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| Java Native | 零配置、支持對象圖、類版本控制 | 體積大、跨語言差、安全風險 | JVM 內部 RMI、Session 複製 |
| JSON | 可讀、跨語言、生態豐富 | 體積較大、無類型信息 | REST API、配置文件、日志 |
| Protobuf/Thrift/Avro | 體積小、快、Schema 演進、跨語言 | 需定義 .proto、學習成本 | 微服務 RPC、高性能傳輸、Kafka |
| Kryo/Hessian | Java 生態高性能、體積小 | 跨語言弱 | Spark/Flink 狀態後端、Dubbo |
// 持久化:支持查詢
List orders = em.createQuery("SELECT o FROM Order o WHERE o.userId = :uid")
.setParameter("uid", 1001).getResultList();
// 序列化:不可查詢,必須全量反序列化
byte[] data = redis.get("user:1001:orders");
List orders = serializer.deserialize(data); // 再在內存過濾