首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java Transient 關鍵字深度解析:序列化與 ORM 框架中的應用實戰

     編輯:Java 程式設計入門

前言

在 Java 開發中,transient 關鍵字與 @Transient 註解雖然名稱相似,但分別服務於 Java 原生序列化機制與 ORM 持久化框架兩個完全不同的領域。本文將通過核心原理講解、實戰代碼演示以及常見誤區分析,幫助開發者徹底掌握它們的正確使用姿勢。

一、Java 原生序列化中的 transient 關鍵字

1.1 核心作用

當類實現 Serializable 接口時,所有非靜態、非 transient 修飾的實例變量都會被自動序列化。若某些字段(如密碼、臨時計算結果、數據庫連接對象)不希望持久化到字節流中,必須使用 transient 關鍵字修飾。

1.2 實戰演示:用戶敏感信息保護

import java.io.*;

public class TransientDemo {
    public static void main(String[] args) {
        User user = new User();
        user.setUsername("Alexia");
        user.setPassword("123456"); // 敏感信息
        
        System.out.println("序列化前: username=" + user.getUsername() + ", password=" + user.getPassword());
        
        // 序列化到文件
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"))) {
            oos.writeObject(user);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // 反序列化恢復
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.dat"))) {
            User restored = (User) ois.readObject();
            System.out.println("反序列化後: username=" + restored.getUsername() + ", password=" + restored.getPassword());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String username;
    private transient String password; // 不參與序列化
    
    // Getter/Setter 省略
}

輸出結果:

序列化前: username=Alexia, password=123456
反序列化後: username=Alexia, password=null

1.3 三大核心規則

  1. 僅修飾變量:不能修飾方法、類或局部變量
  2. 靜態變量天然不序列化:無論是否加 transient,static 字段都不參與序列化(反序列化後取決於當前 JVM 中該類的靜態值)
  3. 自定義類變量需實現 Serializable:若 transient 修飾的是對象引用,該對象類必須實現序列化接口

二、ORM 框架中的 @Transient 註解

2.1 使用場景

在 JPA/Hibernate 等 ORM 框架中,實體類的所有非靜態、非 final 字段默認會映射為數據庫列(隱含 @Basic)。若某字段僅用於業務邏輯計算(如根據出生日期計算年齡),不需持久化到數據庫,必須標註 @Transient。

2.2 代碼示例

@Entity
public class Employee {
    @Id
    private Long id;
    private Date birthDate;
    
    @Transient // 不映射到數據庫列
    public int getAge() {
        return Year.now().getValue() - birthDate.toInstant()
            .atZone(ZoneId.systemDefault()).toLocalDate().getYear();
    }
}

三、常見誤區深度解析

誤區:static + transient 的困惑

許多開發者發現:給 username 加上 static 後,反序列化仍能讀到 "Alexia",似乎與「靜態變量不序列化」矛盾。

真相:靜態變量確實不參與序列化。反序列化後看到的值,是當前 JVM 中該類已加載的靜態字段值,而非從字節流恢復的數據。若在反序列化前修改了靜態值,恢復的對象將反映新值。

四、最佳實踐總結

  • 敏感數據(密碼、Token)必須 transient
  • 衍生屬性(年齡、總價)使用 @Transient 避免數據冗餘
  • 序列化類務必顯式聲明 serialVersionUID
  • 區分 Java 原生序列化與 ORM 持久化兩套體系

掌握 transient 與 @Transient 的邊界與聯繫,能有效避免數據洩露、持久化異常等生產事故,是 Java 進階開發者的必修內功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved