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

POJO、JavaBean、DAO 概念辨析:規範、轉換與分層實踐

     編輯:Java 相關知識

核心定義對比

概念全稱核心約束典型場景關係
POJOPlain Old Java Object無強制約束,普通類,通常有私有字段+公共 getter/setter數據傳輸對象 (DTO)、實體類、VO最寬泛的基類
JavaBean—1. public 無參構造器 2. 私有字段+標準 getter/setter 3. 實現 Serializable 4. 無 public 非靜態字段可視化組件、配置對象、框架數據綁定 (Spring Bean、JSP、序列化)符合規範的 POJO 子集
DAOData Access Object接口/類封裝數據訪問邏輯 (CRUD)、事務邊界、異常轉換持久層:UserDao、OrderDao、MyBatis Mapper、JPA Repository職責角色,非數據結構

代碼形態對比

1. 標準 POJO (最常見)

public class User {
    private Long id;
    private String username;
    private String email;

    // getter/setter (可由 IDE/Lombok 生成)
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    // ... 省略其他
}

2. 標準 JavaBean (符合規範)


import java.io.Serializable;

public class UserConfig implements Serializable { // 1. 實現序列化
    private String theme; // 2. 私有字段
    private int fontSize;

    public UserConfig() {} // 3. public 無參構造器

    // 4. 標準 getter/setter 命名
    public String getTheme() { return theme; }
    public void setTheme(String theme) { this.theme = theme; }
    public int getFontSize() { return fontSize; }
    public void setFontSize(int fontSize) { this.fontSize = fontSize; }
    
    // boolean 類型 getter 可用 is 前綴
    private boolean darkMode;
    public boolean isDarkMode() { return darkMode; }
    public void setDarkMode(boolean darkMode) { this.darkMode = darkMode; }
}

3. DAO 接口與實現


// 接口定義 (面向接口編程)
public interface UserDao {
    User findById(Long id);
    List findAll();
    void insert(User user);
    void update(User user);
    void deleteById(Long id);
}

// MyBatis Mapper 實現 (XML 或註解)
@Mapper
public interface UserMapper extends UserDao {
    @Select("SELECT * FROM users WHERE id = #{id}")
    User findById(Long id);
    
    @Insert("INSERT INTO users(username, email) VALUES(#{username}, #{email})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    void insert(User user);
    // ...
}

// 手寫 JDBC 實現 (教學用)
public class UserDaoJdbcImpl implements UserDao {
    private DataSource dataSource;
    
    @Override
    public User findById(Long id) {
        String sql = "SELECT * FROM users WHERE id = ?";
        try (Connection conn = dataSource.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setLong(1, id);
            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) return mapRow(rs);
            }
        } catch (SQLException e) {
            throw new DataAccessException("查詢失敗", e);
        }
        return null;
    }
    // ...
}

分層架構中的角色定位


┌─────────────────────────────────────┐
│         Controller (VO)             │  ← 接收/返回 View Object (常為 JavaBean)
├─────────────────────────────────────┤
│         Service (BO/DTO)            │  ← 業務邏輯,操作 Business Object / Data Transfer Object
├─────────────────────────────────────┤
│         DAO / Mapper (PO/DO)        │  ← 持久層,操作 Persistent Object / Domain Object (POJO)
├─────────────────────────────────────┤
│         Database (Table)            │
└─────────────────────────────────────┘
  • PO/Entity:與數據庫表映射的 POJO,通常加持久化註解 (`@Entity`, `@Table`)。
  • DTO:服務層間、遠程調用傳輸的 POJO,防止暴露內部模型。
  • VO:控制器返回前端的 POJO,針對視圖定制字段。
  • BO:業務領域模型,封裝業務行為 (DDD 風格)。

常見誤區與最佳實踐

誤區後果正確做法
把 DAO 寫成單例類,裡面放 Connection線程不安全、連接洩漏、事務混亂DAO 無狀態,連接從 DataSource 獲取,配合連接池、事務管理器
Entity 直接作為 Controller 返回值暴露敏感字段 (密碼、鹽值)、循環引用導致序列化爆炸、前端耦合數據庫結構轉換為 VO/DTO,使用 MapStruct/BeanUtils/手寫轉換
JavaBean 必須實現 Serializable非分布式/非持久化場景強制序列化增加開銷僅在跨進程傳輸 (RPC、Session 儲存、緩存) 時實現
Getter/Setter 寫錯導致框架失效MyBatis/Jackson/Spring 綁定失敗嚴格遵循 JavaBean 命名規範,用 Lombok @Data/@Getter/@Setter 保證一致性

Lombok 時代的最佳實踐


// POJO/Entity: 無參構造器 + 全參構造器 + getter/setter + toString/equals/hashCode
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id") // 僅用 id 比較,避免關聯對象循環
@TableName("users") // MyBatis-Plus
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String username;
    private String email;
    private LocalDateTime createTime;
}

// VO: 針對前端定制,可能排除敏感字段、扁平化關聯對象
@Data
@NoArgsConstructor
public class UserVO {
    private Long id;
    private String username;
    private String email; // 不返回 password
    private String roleName; // 扁平化角色名
}

// DTO: 接收參數,校驗註解
@Data
public class UserDTO {
    @NotBlank
    @Size(max = 50)
    private String username;
    
    @Email
    @NotBlank
    private String email;
    
    @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-zA-Z]).{8,20}$")
    private String password; // 僅接收,不返回
}

總結

  • POJO 是統稱:「只是個普通 Java 對象」。
  • JavaBean 是規範:「有無參構造、標準屬性訪問器、可序列化」。
  • DAO 是職責:「封裝數據訪問細節,為上層提供領域語義接口」。
  • 實際開發中,**Entity/DTO/VO 皆為 POJO**,視場景決定是否遵循 JavaBean 規範。**DAO 面向接口編程**,實現細節隔離在持久層框架 (MyBatis/JPA) 或手寫實現中。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved