DAO與repository模式

1.概述

通常,Repository和DAO的實現被認為是可互換的,尤其是在以數據為中心的應用程序中。這引起了他們之間差異的困惑。

在本文中,我們將討論DAO和repository模式之間的區別。

2. DAO模式

數據訪問對像模式(也稱為DAO模式是數據持久性的抽象,被認為更接近於以表為中心的基礎存儲

因此,在許多情況下,我們的DAO與數據庫表匹配,從而提供了一種更直接的方式來從存儲發送/檢索數據,從而隱藏了難看的查詢。

讓我們研究一下DAO模式的簡單實現。

2.1。 User

首先,讓我們創建一個基本的User域類:

public class User {

 private Long id;

 private String userName;

 private String firstName;

 private String email;



 // getters and setters

 }

2.2。 UserDao

然後,我們將創建UserDao接口,該接口為User域提供簡單的CRUD操作:

public interface UserDao {

 void create(User user);

 User read(Long id);

 void update(User user);

 void delete(String userName);

 }

2.3。 UserDaoImpl

最後,我們將創建實現UserDao接口的UserDaoImpl類:

public class UserDaoImpl implements UserDao {

 private final EntityManager entityManager;



 @Override

 public void create(User user) {

 entityManager.persist(user);

 }



 @Override

 public User read(long id) {

 return entityManager.find(User.class, id);

 }



 // ...

 }

在這裡,為簡單起見,我們使用了JPA EntityManager接口與基礎存儲進行交互,並為User域提供了一種數據訪問機制。

3.Repository模式

根據Eric Evans的《 Domain-Driven Design 》一書“Repository是一種封裝存儲,檢索和搜索行為的機制,它模仿對象的集合。”

同樣,根據Patterns of Enterprise Application Architecture它使用類似集合的接口訪問域對象,在域和數據映射層之間進行中介”

換句話說,repository還處理數據並隱藏類似於DAO的查詢。但是,它處於更高的層次,更接近應用程序的業務邏輯。

因此,repository 可以使用DAO從數據庫中獲取數據並填充域對象。或者,它可以從域對象準備數據,然後使用DAO將其發送到存儲系統以實現持久性。

讓我們檢查一下User域的Repository模式的簡單實現。

3.1。 UserRepository

首先,讓我們創建UserRepository接口:

public interface UserRepository {

 User get(Long id);

 void add(User user);

 void update(User user);

 void remove(User user);

 }

在這裡,我們添加了一些通用方法,例如getaddupdateremove以處理對象集合。

3.2。 UserRepositoryImpl

然後,我們將創建UserRepositoryImpl類,提供UserRepository接口的實現:

public class UserRepositoryImpl implements UserRepository {

 private UserDaoImpl userDaoImpl;



 @Override

 public User get(Long id) {

 User user = userDaoImpl.read(id);

 return user;

 }



 @Override

 public void add(User user) {

 userDaoImpl.create(user);

 }



 // ...

 }

在這裡,我們使用了UserDaoImpl從數據庫添加/檢索數據。

到目前為止,我們可以說DAO和存儲庫的實現看起來非常相似,因為User類是貧血領域。而且,repository只是數據訪問層(DAO)之上的另一層。

但是,DAO似乎是訪問數據的理想選擇,而repository是實現業務用例的理想方式

4.具有多個DAO的存儲庫模式

為了清楚地理解最後一條語句,讓我們增強User域以處理業務用例。

想像一下,我們想通過匯總用戶的Twitter推文,Facebook帖子等來準備用戶的社交媒體資料。

4.1。 Tweet

首先,我們將創建Tweet類,其中包含一些用於保存tweet信息的屬性:

public class Tweet {

 private String email;

 private String tweetText;

 private Date dateCreated;



 // getters and setters

 }

4.2。 TweetDaoTweetDaoImpl

然後,類似於UserDao ,我們將創建TweetDao接口,該接口允許獲取推文:

public interface TweetDao {

 List<Tweet> fetchTweets(String email);

 }

同樣,我們將創建TweetDaoImpl類,該類提供fetchTweets方法的實現:

public class TweetDaoImpl implements TweetDao {

 @Override

 public List<Tweet> fetchTweets(String email) {

 List<Tweet> tweets = new ArrayList<Tweet>();



 //call Twitter API and prepare Tweet object



 return tweets;

 }

 }

在這裡,我們將調用Twitter API,以使用戶使用其電子郵件獲取所有推文。

因此,在這種情況下,DAO使用第三方API提供了一種數據訪問機制。

4.3。增強User

最後,讓我們創建User類的UserSocialMedia子類,以保留Tweet對象的列表:

public class UserSocialMedia extends User {

 private List<Tweet> tweets;



 // getters and setters

 }

在這裡,我們的UserSocialMedia類是一個複雜域,也包含User域的屬性。

4.4。 UserRepositoryImpl

現在,我們將升級UserRepositoryImpl類,以提供一個User域對像以及一條推文列表:

public class UserRepositoryImpl implements UserRepository {

 private UserDaoImpl userDaoImpl;

 private TweetDaoImpl tweetDaoImpl;



 @Override

 public User get(Long id) {

 UserSocialMedia user = (UserSocialMedia) userDaoImpl.read(id);



 List<Tweet> tweets = tweetDaoImpl.fetchTweets(user.getEmail());

 user.setTweets(tweets);



 return user;

 }

 }

在這裡, UserRepositoryImpl使用提取用戶數據UserDaoImpl使用和用戶的鳴叫TweetDaoImpl.

然後,它將匯總這兩組信息並提供UserSocialMedia類的域對象,該類對UserSocialMedia對於我們的業務用例非常方便。因此,repository依賴於DAO來訪問來自各種來源的數據

同樣,我們可以增強我們的User域,以保留Facebook帖子列表。

5.比較兩種模式

現在,我們已經了解了DAO和repository模式的細微差別,讓我們總結一下它們的區別:

  • DAO是數據持久性的抽象。但是,repository是對象集合的抽象
  • DAO是一個較低層的概念,更接近於存儲系統。但是repository是一個更高級的概念,更接近於域對象
  • DAO充當數據映射/訪問層,隱藏了難看的查詢。但是,repository是域和數據訪問層之間的一層,隱藏了整理數據和準備域對象的複雜性
  • DAO不能使用存儲庫來實現。但是,repository可以使用DAO訪問基礎存儲

另外,如果我們有一個貧血域,則repository將只是DAO。

此外,repository模式鼓勵域驅動的設計,也使非技術團隊成員也容易理解數據結構

六,結論

在本文中,我們探討了DAO和repository模式之間的差異。

首先,我們研究了DAO模式的基本實現。然後,我們看到了使用存儲庫模式的類似實現。

最後,我們研究了使用多個DAO的存儲庫,該存儲庫增強了域解決業務用例的能力。

因此,我們可以得出結論,當應用程序從以數據為中心轉向面向業務時,存儲庫模式證明是一種更好的方法。

像往常一樣,所有代碼實現都可以在GitHub上獲得