DAO vs Corak Repositori

1. Gambaran keseluruhan

Selalunya, pelaksanaan repositori dan DAO dianggap boleh ditukar ganti, terutama dalam aplikasi yang berpusatkan data. Ini menimbulkan kekeliruan mengenai perbezaan mereka.

Dalam artikel ini, kita akan membincangkan perbezaan antara DAO dan corak Repositori.

2. Corak DAO

Pola Objek Akses Data, atau Pola DAO , merupakan pengabstrakan data ketekunan dan dianggap lebih dekat dengan penyimpanan yang mendasari, yang sering berpusat pada jadual .

Oleh itu, dalam banyak kes, DAO kami sepadan dengan jadual pangkalan data, yang membolehkan kaedah yang lebih mudah untuk menghantar / mengambil data dari storan, menyembunyikan pertanyaan yang jelek.

Mari kita periksa pelaksanaan sederhana corak DAO.

2.1. Pengguna

Pertama, mari buat kelas domain pengguna asas :

public class User { private Long id; private String userName; private String firstName; private String email; // getters and setters }

2.2. PenggunaDao

Kemudian, kami akan membuat antara muka UserDao yang menyediakan operasi CRUD mudah untuk domain Pengguna :

public interface UserDao { void create(User user); User read(Long id); void update(User user); void delete(String userName); }

2.3. PenggunaDaoImpl

Terakhir, kami akan membuat kelas UserDaoImpl yang menerapkan antara muka UserDao :

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); } // ... }

Di sini, untuk kesederhanaan, kami telah menggunakan antara muka JPA EntityManager untuk berinteraksi dengan penyimpanan yang mendasari dan menyediakan mekanisme akses data untuk domain Pengguna .

3. Corak Repositori

Menurut buku Eric Evans, Domain-Driven Design , "repositori adalah mekanisme untuk merangkumi penyimpanan, pengambilan, dan perilaku pencarian, yang meniru koleksi objek."

Demikian juga, menurut Pola Arsitektur Aplikasi Perusahaan , ia "memediasi antara domain dan lapisan pemetaan data menggunakan antarmuka seperti pengumpulan untuk mengakses objek domain."

Dengan kata lain, repositori juga berkaitan dengan data dan menyembunyikan pertanyaan yang serupa dengan DAO. Walau bagaimanapun, ia berada di tahap yang lebih tinggi, lebih dekat dengan logik perniagaan aplikasi.

Akibatnya, repositori dapat menggunakan DAO untuk mengambil data dari pangkalan data dan mengisi objek domain. Atau, ia dapat menyiapkan data dari objek domain dan mengirimkannya ke sistem penyimpanan menggunakan DAO untuk kegigihan.

Mari kita periksa pelaksanaan sederhana corak Repositori untuk domain Pengguna .

3.1. Penyimpanan Pengguna

Pertama, mari buat antaramuka UserRepository :

public interface UserRepository { User get(Long id); void add(User user); void update(User user); void remove(User user); }

Di sini, kami telah menambahkan beberapa kaedah biasa seperti mendapatkan , menambah , mengemas kini , dan membuang untuk berfungsi dengan pengumpulan objek.

3.2. UserRepositoryImpl

Kemudian, kami akan membuat kelas UserRepositoryImpl yang menyediakan pelaksanaan antara muka 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); } // ... }

Di sini, kami telah menggunakan UserDaoImpl untuk menghantar / mengambil data dari pangkalan data.

Sejauh ini, kita dapat mengatakan bahawa pelaksanaan DAO dan repositori kelihatan sangat serupa kerana kelas Pengguna adalah domain anemia. Dan, repositori hanyalah lapisan lain di atas lapisan akses data (DAO).

Walau bagaimanapun, DAO nampaknya calon yang tepat untuk mengakses data, dan repositori adalah cara yang ideal untuk melaksanakan kes penggunaan perniagaan .

4. Corak Repositori Dengan Pelbagai DAO

Untuk memahami pernyataan terakhir dengan jelas, mari tingkatkan domain Pengguna kami untuk menangani kes penggunaan perniagaan.

Bayangkan kita mahu menyiapkan profil media sosial pengguna dengan mengumpulkan tweet Twitter, catatan Facebook dan banyak lagi.

4.1. Tweet

Pertama, kami akan membuat kelas Tweet dengan beberapa sifat yang menyimpan maklumat tweet:

public class Tweet { private String email; private String tweetText; private Date dateCreated; // getters and setters }

4.2. TweetDao dan TweetDaoImpl

Kemudian, sama dengan UserDao , kami akan membuat antara muka TweetDao yang membolehkan mengambil tweet:

public interface TweetDao { List fetchTweets(String email); }

Begitu juga, kami akan membuat kelas TweetDaoImpl yang menyediakan pelaksanaan kaedah fetchTweets :

public class TweetDaoImpl implements TweetDao { @Override public List fetchTweets(String email) { List tweets = new ArrayList(); //call Twitter API and prepare Tweet object return tweets; } }

Di sini, kami akan memanggil API Twitter untuk mengambil semua tweet oleh pengguna menggunakan e-melnya.

Jadi, dalam kes ini, DAO menyediakan mekanisme akses data menggunakan API pihak ketiga.

4.3. Tingkatkan Domain Pengguna

Terakhir, mari buat subkelas UserSocialMedia kelas Pengguna kami untuk menyimpan senarai objek Tweet :

public class UserSocialMedia extends User { private List tweets; // getters and setters }

Here, our UserSocialMedia class is a complex domain containing the properties of the User domain too.

4.4. UserRepositoryImpl

Now, we'll upgrade our UserRepositoryImpl class to provide a User domain object along with a list of tweets:

public class UserRepositoryImpl implements UserRepository { private UserDaoImpl userDaoImpl; private TweetDaoImpl tweetDaoImpl; @Override public User get(Long id) { UserSocialMedia user = (UserSocialMedia) userDaoImpl.read(id); List tweets = tweetDaoImpl.fetchTweets(user.getEmail()); user.setTweets(tweets); return user; } }

Here, the UserRepositoryImpl extracts user data using the UserDaoImpl and user's tweets using the TweetDaoImpl.

Then, it aggregates both sets of information and provides a domain object of the UserSocialMedia class that is handy for our business use-case. Therefore, a repository relies on DAOs for accessing data from various sources.

Similarly, we can enhance our User domain to keep a list of Facebook posts.

5. Comparing the Two Patterns

Now that we've seen the nuances of the DAO and Repository patterns, let's summarize their differences:

  • DAO is an abstraction of data persistence. However, a repository is an abstraction of a collection of objects
  • DAO is a lower-level concept, closer to the storage systems. However, Repository is a higher-level concept, closer to the Domain objects
  • DAO works as a data mapping/access layer, hiding ugly queries. However, a repository is a layer between domains and data access layers, hiding the complexity of collating data and preparing a domain object
  • DAO can't be implemented using a repository. However, a repository can use a DAO for accessing underlying storage

Also, if we have an anemic domain, the repository will be just a DAO.

Additionally, the repository pattern encourages a domain-driven design, providing an easy understanding of the data structure for non-technical team members, too.

6. Conclusion

In this article, we explored differences between DAO and Repository patterns.

First, we examined a basic implementation of the DAO pattern. Then, we saw a similar implementation using the Repository pattern.

Last, we looked at a Repository utilizing multiple DAOs, enhancing the capabilities of a domain to solve a business use-case.

Therefore, we can conclude that the Repository pattern proves a better approach when an app moves from being data-centric to business-oriented.

As usual, all the code implementations are available over on GitHub.