Java 中儲存庫模式和 DAO 之間的區別

Mehvish Ashiq 2023年1月30日 2022年7月18日
  1. 資料訪問物件模式
  2. 儲存庫模式
  3. Java 中資料訪問物件 (DAO) 和儲存庫模式之間的區別
  4. DAO 和儲存庫模式實現之間的區別
Java 中儲存庫模式和 DAO 之間的區別

今天,我們將瞭解資料訪問物件 (DAO) 和儲存庫模式。本文還介紹了它們之間的差異。

資料訪問物件模式

這種模式是資料持久化的抽象,也被認為更接近底層儲存,主要以表為中心。這就是為什麼在大多數情況下,資料訪問物件 (DAO) 與資料庫表相匹配,從而允許最直接的方法從儲存中檢索和傳送資料,同時隱藏醜陋的查詢。

儲存庫模式

儲存庫模式是從我們的應用程式中檢索儲存資料的過程,它隱藏了資料儲存系統的各個方面。以下是儲存庫介面,可讓我們通過其 username 查詢一個 User

interface UserRepository {
    User findUserByUsername( Username name );
}

這可以基於我們的儲存技術進行一個或多個實施,例如 MySQL、Amazon DynamoDB、Web Service、Oracle 或其他。

我們也可以說儲存庫模式是一種將資料來源與應用程式的其餘部分隔離開來的設計模式。儲存庫在資料來源(例如 Web 服務和持久模型)和應用程式的其餘部分之間進行調解。

以下是儲存庫模式使用的圖形表示。

java 中 repository 模式和 dao 的區別——repository 視覺化

你理解正確,儲存庫類似於 Data Access Object (DAO),但它是一種抽象,它隱藏了用於從業務邏輯中檢索資料的所有邏輯。

它的行為類似於模型的包裝器,負責從持久儲存中訪問資料。使用儲存庫的好處是它將我們的東西如何儲存的精確細節與使用它的應用程式分開。

這對於測試非常重要,因為我們可以編寫總是返回一個使用者但不訪問資料庫的存根程式碼。它使我們擺脫了各種問題,讓我們可以為我們的應用程式程式碼編寫快速的單元測試,這將不依賴於儲存的資料。

Java 中資料訪問物件 (DAO) 和儲存庫模式之間的區別

主要區別在於儲存庫僅返回撥用層可以理解的物件。大多數情況下,儲存庫由業務層使用,因此它輸出業務物件。

另一方面,資料訪問物件返回可能/可能不是整個業務物件的資料。這意味著資料不是有效的業務概念。

如果我們的業務物件只是資料結構,那麼它可以暗示我們有建模問題。這意味著糟糕的設計,而至少正確封裝物件的儲存庫將更有意義。

如果我們只是載入或儲存資料結構,那麼很可能我們不需要儲存庫。物件關係對映(ORM)就足夠了。

如果我們必須處理由各種其他物件(聚合)組成的業務物件,並且該特定物件要求其所有部分保持一致(聚合根),儲存庫模式是最佳解決方案。

這是因為它抽象了完整的永續性資訊。我們的應用程式只要求一個產品,並且儲存庫將其作為一個整體返回;恢復物件需要多少查詢/表並不重要。

請記住,業務物件不是物件關係對映 (ORM) 實體。這可能是從技術的角度來看,但考慮到設計,一個模型是業務的東西,另一個模型是永續性的東西。

大多數時候,沒有直接的相容性。

以下是我們更喜歡使用儲存庫模式的一些情況:

  • 它用於我們有許多繁重查詢的系統中。
  • 我們使用儲存庫模式來避免重複查詢。
  • 它用於資料儲存和域(實體)之間。
  • 它還用於使用為其建立儲存庫的實體規範搜尋和刪除元素。

現在,讓我們通過程式碼實現來了解這種差異。

DAO 和儲存庫模式實現之間的區別

讓我們從資料訪問物件模式的實現開始。

資料訪問物件模式實現

在這裡,我們需要有下面列出的三個類:

  1. 一個基本的 Employee 域類
  2. EmployeeDAO 介面,為 Employee 域提供簡單的 CRUD 操作
  3. 實現 EmployeeDAO 介面的 EmployeeDAOImplementation

示例程式碼(員工類):

public class Employee {
    private Long id;
    private String employeeCode;
    private String firstName;
    private String email;

    // write your getters/setters
}

示例程式碼(EmployeeDAO 介面):

public interface EmployeeDAO {
    void create(Employee employee);
    Employee read(Long id);
    void update(Employee employee);
    void delete(String employeeCode);
}

示例程式碼(EmployeeDAOImplementation 類):

public class EmployeeDAOImplementation implements EmployeeDAO {
    private final EntityManager entityManager;

    @Override
    public void create(Employee employee) {
        entityManager.persist(employee);
    }

    @Override
    public Employee read(long id) {
        return entityManager.find(Employee.class, id);
    }

    // ... continue with remaining code
}

我們正在使用 JPA EntityManager Interface 與底層儲存進行通訊。此外,為 Employee 域提供資料訪問機制。

儲存庫模式實現

該模式封裝了儲存、搜尋行為和檢索,模擬了物件的集合。與 DAO 一樣,它也隱藏查詢和處理資料,但位於更接近應用程式業務邏輯的更高階別。

儲存庫也可以使用 DAO 從資料庫中獲取資料。此外,它可以填充域物件或從域準備資料,然後使用 DAO 將其傳送到儲存系統以進行永續性。

在這裡,我們需要以下類:

  1. EmployeeRepository 介面
  2. EmployeeRepositoryImplementation

示例程式碼(EmployeeRepository 介面):

public interface EmployeeRepository {
    Employee get(Long id);
    void add(Employee employee);
    void update(Employee employee);
    void remove(Employee employee);
}

示例程式碼(EmployeeRepositoryImplementation 類):

public class EmployeeRepositoryImplementation implements EmployeeRepository {
    private EmployeeDAOImplementation employeeDAOImplementation;

    @Override
    public Employee get(Long id) {
        Employee employee = employeeDAOImplementation.read(id);
        return employee;
    }

    @Override
    public void add(Employee employee) {
        employeeDAOImplementation.create(employee);
    }

    // ... continue with remaining code
}

在這裡,我們使用 EmployeeDAOImplementation 從資料庫中檢索/傳送資料。所以,我們可以說儲存庫的實現和 DAO 看起來很相似。

這是因為 Employee 類是貧血領域,而儲存庫只是資料訪問層 (DAO) 之上的另一層;但是,儲存庫是實現業務用例的最佳方式。相比之下,資料訪問物件看起來很適合訪問資料。

Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook