Apa perbedaan antara pola DAO dan Repositori?

423

Apa perbedaan antara Data Access Objects (DAO) dan pola Repositori? Saya mengembangkan aplikasi menggunakan Enterprise Java Beans (EJB3), Hibernate ORM sebagai infrastruktur, dan Domain-Driven Design (DDD) dan Test-Driven Development (TDD) sebagai teknik desain.

Thurein
sumber

Jawaban:

472

DAOadalah abstraksi dari kegigihan data .
Repositoryadalah abstraksi dari kumpulan benda .

DAOakan dianggap lebih dekat ke database, sering kali tabel-sentris.
Repositoryakan dianggap lebih dekat ke Domain, hanya berurusan di Agregat Roots.

Repositorydapat diimplementasikan menggunakan DAO, tetapi Anda tidak akan melakukan yang sebaliknya.

Juga, Repositoryumumnya antarmuka yang lebih sempit. Ini harus menjadi hanya koleksi benda-benda, dengan Get(id), Find(ISpecification), Add(Entity).

Metode seperti Updateini sesuai untuk perubahan DAO, tetapi bukan a Repository- saat menggunakan Repository, entitas yang biasanya akan dilacak oleh UnitOfWork yang terpisah.

Tampaknya umum untuk melihat implementasi yang disebut Repositorybenar-benar lebih DAO, dan karenanya saya pikir ada beberapa kebingungan tentang perbedaan di antara mereka.

quentin-starin
sumber
27
Nah, Anda tidak ingin kelas DAO Anda benar-benar mengimplementasikan IRepositoryantarmuka Anda . Anda ingin repositori Anda menggunakan DAO dalam implementasinya. Ingat, DAO akan menjadi objek per-tabel, sedangkan Repositori hampir selalu harus menggunakan beberapa DAO untuk membangun Entitas tunggal. Jika ternyata bukan itu masalahnya, Repositori dan Entitas Anda hanya perlu mengakses satu tabel, maka kemungkinan besar Anda membangun domain anemia.
quentin-starin
29
Saya perhatikan di dunia .NET khususnya istilah "Gudang" digunakan untuk merujuk pada apa yang pada dasarnya adalah DAO; "DAO" lebih merupakan istilah Jawa.
Wayne Molina
14
@Thurein DAO-s tidak per tabel, polanya hanya mengabstraksi akses ke data Anda - Anda dapat mengimplementasikannya sesuka Anda (per tabel, atau per grup atau model). Cara yang disarankan adalah untuk selalu membentuk DAO Anda berdasarkan pada model domain Anda daripada mempertimbangkan ketekunan yang mendasarinya karena itu membuatnya lebih mudah / lebih jelas untuk digunakan dan memberi Anda sedikit lebih banyak fleksibilitas tentang bagaimana Anda bertahannya (mis. Bayangkan Anda akan membutuhkan DAO yang menyimpan data Anda dalam file XML atau mendapatkannya dari antrian pesan daripada dari Database ...).
Stef
21
@Stef saya tidak setuju. DAO mengembalikan data dengan definisi yang sangat ( objek akses data ). Repositori, menurut definisinya, mengembalikan objek domain. Seharusnya beralasan bahwa repositori akan menggunakan DAO dan bukan sebaliknya, karena dalam OOP kami membuat objek domain dari satu atau lebih objek data, dan bukan sebaliknya.
Mihai Danila
6
Mengapa Repositori adalah konsep "Hanya Baca" sementara DAO adalah "Baca dan Tulis"?
Dennis
121

OK, pikir saya bisa menjelaskan lebih baik apa yang saya masukkan dalam komentar :). Jadi, pada dasarnya, Anda dapat melihat keduanya sebagai sama, meskipun DAO adalah pola yang lebih fleksibel daripada Repositori. Jika Anda ingin menggunakan keduanya, Anda akan menggunakan Repositori di DAO-s Anda. Saya akan menjelaskan masing-masing di bawah ini:

GUDANG:

Ini adalah repositori dari jenis objek tertentu - ini memungkinkan Anda untuk mencari jenis objek tertentu serta menyimpannya. Biasanya itu HANYA akan menangani satu jenis objek. Misalnya AppleRepositoryakan memungkinkan Anda untuk melakukan AppleRepository.findAll(criteria)atau AppleRepository.save(juicyApple). Perhatikan bahwa Repositori menggunakan istilah Model Domain (bukan istilah DB - tidak ada yang terkait dengan bagaimana data disimpan di mana saja).

Repositori kemungkinan besar akan menyimpan semua data dalam tabel yang sama, sedangkan polanya tidak mengharuskan itu. Fakta bahwa itu hanya menangani satu jenis data, membuatnya secara logis terhubung ke satu tabel utama (jika digunakan untuk kegigihan DB).

DAO - objek akses data (dengan kata lain - objek yang digunakan untuk mengakses data)

DAO adalah kelas yang mencari data untuk Anda (sebagian besar adalah pencari, tetapi biasanya juga digunakan untuk menyimpan data). Pola ini tidak membatasi Anda untuk menyimpan data dari jenis yang sama, sehingga Anda dapat dengan mudah memiliki DAO yang menempatkan / menyimpan objek terkait.

Misalnya Anda dapat dengan mudah memiliki UserDao yang memperlihatkan metode seperti

Collection<Permission> findPermissionsForUser(String userId)
User findUser(String userId)
Collection<User> findUsersForPermission(Permission permission)

Semua itu terkait dengan Pengguna (dan keamanan) dan dapat ditentukan berdasarkan DAO yang sama. Ini bukan kasus untuk Repositori.

Akhirnya

Perhatikan bahwa kedua pola benar-benar berarti sama (mereka menyimpan data dan mereka abstrak aksesnya dan keduanya diekspresikan lebih dekat ke model domain dan hampir tidak mengandung referensi DB), tetapi cara mereka digunakan bisa sedikit berbeda, DAO menjadi sedikit lebih fleksibel / generik, sementara Repositori sedikit lebih spesifik dan terbatas pada tipe saja.

Stef
sumber
Jika saya mendapatkan ini dengan benar, misalnya saya memiliki sesuatu seperti CarDescriptionyang memiliki misalnya language_idsebagai kunci asing - maka untuk mengambil bahwa saya harus melakukan sesuatu seperti ini: CarRepository.getAll(new Criteria(carOwner.id, language.id));yang akan memberi saya semua mobil bahasa dalam bahasa tertentu - adalah cara yang tepat untuk melakukannya ?
displayname
@StefanFalk, lihatlah pada Data Spring, ini memungkinkan Anda untuk melakukan panggilan jauh lebih baik dari itu. mis. itu bisa ditulis seperti CarRepository.findByLanguageId(language.id)dan Anda bahkan tidak perlu menulis kode, Anda cukup mendefinisikan antarmuka dengan metode dengan nama itu dan Spring Data menangani pembangunan implementasi kelas default untuk Anda. Hal-hal yang cukup rapi;)
Stef
2
Keindahan dari Spring Data adalah bahwa Anda tidak benar-benar harus menulis kueri, Anda hanya membuat antarmuka (seperti itu TodoRepository dalam contoh Anda, yang memiliki metode findById). Dan Anda praktis sudah selesai. Apa yang dilakukan oleh Spring Data adalah, ia menemukan semua antarmuka yang Anda buat yang memperluas antarmuka Repositori dan membuat kelas untuk Anda. Anda tidak akan pernah melihat kelas-kelas itu dan Anda tidak akan dapat membuat instance baru, tetapi Anda tidak perlu karena Anda hanya dapat autowire antarmuka dan membiarkan Spring menemukan objek repositori itu.
Stef
1
Akhirnya, Anda tidak harus menggunakan Data Musim Semi, Anda bisa menggunakan cara lama untuk menulis metode kueri sendiri (menggunakan API Kriteria dll), tetapi Anda hanya akan membuat hidup Anda sedikit lebih rumit ... Anda mungkin mengatakan bahwa Anda akan memiliki lebih banyak fleksibilitas seperti itu, tetapi itu tidak benar baik jika Anda benar-benar ingin menjadi gila dengan pertanyaan Anda, Spring Data memungkinkan Anda dua cara untuk melakukannya: penjelasan @Query, atau jika itu tidak berhasil, Anda dapat buat repositori khusus yang merupakan ekstensi yang memberi Anda kekuatan yang sama seperti jika Anda menulis implementasi Anda sendiri dari awal.
Stef
2
"Aggregated root" adalah istilah yang sering dihubungkan dengan pola repositori. Saya tidak tahu bagaimana Anda akan menggunakannya dengan definisi repositori Anda.
Christian Strempfer
90

DAO dan pola Repositori adalah cara menerapkan Lapisan Akses Data (DAL). Jadi, mari kita mulai dengan DAL, pertama.

Aplikasi berorientasi objek yang mengakses database, harus memiliki logika untuk menangani akses database. Untuk menjaga kode tetap bersih dan modular, direkomendasikan bahwa logika akses database harus diisolasi menjadi modul terpisah. Dalam arsitektur berlapis, modul ini adalah DAL.

Sejauh ini, kami belum membicarakan implementasi tertentu: hanya prinsip umum yang menempatkan logika akses database dalam modul terpisah.

Sekarang, bagaimana kita dapat menerapkan prinsip ini? Nah, orang yang tahu cara mengimplementasikan ini, khususnya dengan kerangka kerja seperti Hibernate, adalah pola DAO.

Pola DAO adalah cara menghasilkan DAL, di mana biasanya, setiap entitas domain memiliki DAO sendiri. Misalnya, Userdan UserDao, Appointmentdan AppointmentDao, dll. Contoh DAO dengan Hibernate: http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html .

Lalu apa pola Repositori? Seperti DAO, pola Repositori juga merupakan cara mencapai DAL. Poin utama dalam pola Repositori adalah bahwa, dari perspektif klien / pengguna, harus terlihat atau berperilaku sebagai koleksi. Apa yang dimaksud dengan berperilaku seperti koleksi bukanlah berarti harus dibuat seperti Collection collection = new SomeCollection(). Alih-alih, itu berarti harus mendukung operasi seperti menambah, menghapus, memuat, dll. Ini adalah inti dari pola Repositori.

Dalam praktiknya, misalnya dalam hal menggunakan Hibernate, pola Repositori diwujudkan dengan DAO. Itu adalah turunan dari DAL dapat sekaligus contoh dari pola DAO dan pola Repositori.

Pola repositori belum tentu sesuatu yang dibangun di atas DAO (seperti beberapa mungkin menyarankan). Jika DAO dirancang dengan antarmuka yang mendukung operasi yang disebutkan di atas, maka itu adalah turunan dari pola Repositori. Pikirkan tentang hal ini, Jika DAO sudah menyediakan serangkaian operasi seperti pengumpulan, lalu apa perlunya lapisan tambahan di atasnya?

Nazar Merza
sumber
5
"Jika DAO sudah menyediakan kumpulan operasi seperti pengumpulan, lalu apa perlunya lapisan tambahan di atasnya?" Misalkan Anda memodelkan toko hewan peliharaan dan Anda memiliki meja 'PetType' dengan hewan yang berbeda dan atributnya (nama: "Kucing", ketik: "Mamalia", dll.) Yang dirujuk oleh tabel 'Hewan Peliharaan' dari hewan peliharaan beton yang Anda ada di toko (nama: "Katniss", berkembang biak: "Calico", dll). Jika Anda ingin menambahkan hewan jenis yang belum ada di database, Anda bisa menggunakan repositori untuk mengelompokkan dua panggilan DAO yang terpisah (satu untuk membuat PetType dan yang lainnya untuk Pet) dalam satu metode, menghindari penggandengan dalam DAO
Matt
1
Penjelasan luar biasa, Tuan!
Paul-Sebastian Manole
74

Terus terang, ini terlihat seperti perbedaan semantik, bukan perbedaan teknis. Frasa Objek Akses Data tidak merujuk ke "database" sama sekali. Dan, meskipun Anda bisa mendesainnya menjadi basis data-sentris, saya pikir kebanyakan orang akan mempertimbangkan untuk melakukan kesalahan desain.

Tujuan DAO adalah untuk menyembunyikan detail implementasi dari mekanisme akses data. Apa perbedaan pola Repositori? Sejauh yang saya tahu, itu tidak benar. Mengatakan Repositori berbeda dengan DAO karena Anda berurusan dengan / mengembalikan koleksi objek tidak benar; DAO juga dapat mengembalikan koleksi benda.

Semua yang saya baca tentang pola repositori tampaknya bergantung pada perbedaan ini: desain DAO yang buruk vs desain DAO yang baik (alias pola desain repositori).

rakehell404
sumber
5
ya, sepenuhnya setuju, mereka pada dasarnya sama. DAO terdengar lebih terkait DB, tetapi tidak. Sama seperti Repositori, itu hanya abstraksi yang digunakan untuk menyembunyikan di mana dan bagaimana data berada.
Stef
+1 Untuk pernyataan ini. Terus terang, ini terlihat seperti perbedaan semantik, bukan perbedaan teknis. Frasa Objek Akses Data tidak merujuk ke "database" sama sekali.
Sudhakar Chavali
1
Titik ketika membandingkan Repositori dan koleksi tidak bahwa mereka berhadapan / kembali koleksi benda-benda, tapi itu Repositori berperilaku seolah-olah mereka adalah koleksi sendiri. Misalnya, di Jawa itu berarti bahwa Repositori tidak memiliki metode pembaruan karena ketika Anda memodifikasi objek dalam koleksi itu diperbarui secara otomatis (karena koleksi Java hanya menyimpan referensi ke objek).
Christoph Böhme
6

Perbedaan utama adalah bahwa repositori menangani akses ke akar agregat dalam agregat, sementara DAO menangani akses ke entitas. Oleh karena itu, itu umum bahwa repositori mendelegasikan ketekunan aktual dari akar agregat ke DAO. Selain itu, karena akar agregat harus menangani akses entitas lain, maka mungkin perlu mendelegasikan akses ini ke DAO lain.

pablochacin
sumber
5

DAO menyediakan abstraksi pada basis data / file data atau mekanisme ketekunan lainnya sehingga, lapisan ketekunan dapat dimanipulasi tanpa mengetahui detail implementasinya.

Sedangkan dalam kelas Repositori, beberapa kelas DAO dapat digunakan di dalam metode Repositori tunggal untuk menyelesaikan operasi dari "perspektif aplikasi". Jadi, alih-alih menggunakan beberapa DAO di lapisan Domain, gunakan repositori untuk menyelesaikannya. Repositori adalah lapisan yang mungkin mengandung beberapa logika aplikasi seperti: Jika data tersedia dalam cache di memori kemudian mengambilnya dari cache sebaliknya, mengambil data dari jaringan dan menyimpannya di dalam cache dalam memori untuk pengambilan berikutnya.

Rahul Rastogi
sumber
3

Repositori hanyalah DAO yang dirancang dengan baik.

ORM adalah tabel sentris tetapi bukan DAO.

Tidak perlu menggunakan beberapa DAO dalam repositori karena DAO itu sendiri dapat melakukan hal yang persis sama dengan repositori / entitas ORM atau penyedia DAL, tidak peduli di mana dan bagaimana mobil bertahan 1 tabel, 2 tabel, n tabel, setengah tabel, a layanan web, tabel, dan layanan web, dll. Layanan menggunakan beberapa DAO / repositori.

DAO saya sendiri, katakanlah CarDao hanya berurusan dengan Mobil DTO, maksud saya, hanya mengambil input Mobil DTO dan hanya mengembalikan mobil DTO atau koleksi mobil DTO dalam output.

Jadi seperti halnya Repositori, DAO sebenarnya adalah IoC, untuk logika bisnis, yang memungkinkan antarmuka kegigihan tidak diintimidasi oleh strategi atau warisan kegigihan. DAO merangkum strategi ketekunan dan menyediakan antarmuka ketekunan terkait domaine. Repositori hanyalah kata lain bagi mereka yang belum memahami apa sebenarnya DAO yang didefinisikan dengan baik.

Cyril
sumber
Pertama-tama "repositori / entitas ORM"? Maksud Anda entitas ORM. Tidak ada yang namanya repositori ORM. Kedua dari semua ORM biasanya hanya berurusan dengan entitas, yaitu. model domain. DAO berurusan dengan tabel secara langsung dan akses data abstrak. Mereka mengembalikan entitas juga. Repositori adalah abstraksi tertinggi, menawarkan antarmuka koleksi untuk mendapatkan entitas. DAO dapat berupa repositori, mis. abstraksi mesin penyimpanan aktual, menawarkan antarmuka untuk itu dan juga menawarkan tampilan koleksi entitas (cache). DAO dapat menggunakan ORM untuk berinteraksi dengan basis data dan mendelegasikan operasi entitas.
Paul-Sebastian Manole
3
Setuju dengan @brokenthorn. Poin paling penting dalam komentarnya adalah "Repositori adalah abstraksi tertinggi," dan abstraksi ini menjadi keharusan ketika Anda ingin melindungi kode domain Anda dari teknologi basis data yang mendasarinya. Konsep ORM / Adapter / DB Driver cenderung bocor ke DAO. Jika Anda memiliki aplikasi yang mendukung lebih dari satu teknologi basis data, atau jika Anda ingin aplikasi Anda tidak dikunci ke basis data, menggunakan DAO langsung dari model domain adalah hal yang tidak perlu.
Subhash Bhushan
2

Cobalah untuk mencari tahu apakah DAO atau pola Repositori paling berlaku untuk situasi berikut: Bayangkan Anda ingin memberikan API akses data yang seragam untuk mekanisme persisten ke berbagai jenis sumber data seperti RDBMS, LDAP, OODB, repositori XML dan file datar.

Lihat juga tautan berikut, jika tertarik:

http://www.codeinsanity.com/2008/08/repository-pattern.html

http://blog.fedecarg.com/2009/03/15/domain-driven-design-the-repository/

http://devlicio.us/blogs/casey/archive/2009/02/20/ddd-the-repository-pattern.aspx

http://en.wikipedia.org/wiki/Domain-driven_design

http://msdn.microsoft.com/en-us/magazine/dd419654.aspx

javaDisciple
sumber
0

dalam kalimat yang sangat sederhana: Perbedaan signifikan adalah bahwa Repositori mewakili koleksi, sementara DAO lebih dekat ke database, seringkali jauh lebih sentris-tabel.

Alireza Rahmani Khalili
sumber
DAO juga dapat mewakili koleksi / objek ...
Yousha Aleayoub
0

Dalam kerangka kerja pegas, ada anotasi yang disebut repositori, dan dalam uraian anotasi ini, ada informasi berguna tentang repositori, yang menurut saya berguna untuk diskusi ini.

Menunjukkan bahwa kelas beranotasi adalah "Repositori", awalnya didefinisikan oleh Domain-Driven Design (Evans, 2003) sebagai "mekanisme untuk merangkum penyimpanan, pengambilan, dan perilaku pencarian yang mengemulasi kumpulan objek".

Tim yang menerapkan pola Java EE tradisional seperti "Objek Akses Data" juga dapat menerapkan stereotip ini ke kelas DAO, meskipun harus berhati-hati untuk memahami perbedaan antara Objek Akses Data dan repositori gaya DDD sebelum melakukannya. Anotasi ini adalah stereotip tujuan umum dan tim individu dapat mempersempit semantik dan menggunakannya sebagaimana mestinya.

Kelas dengan demikian memenuhi syarat untuk terjemahan Spring DataAccessException bila digunakan bersama dengan PersistenceExceptionTranslationPostProcessor. Kelas beranotasi juga diklarifikasi mengenai perannya dalam arsitektur aplikasi keseluruhan untuk tujuan perkakas, aspek, dll.

Ali Yeganeh
sumber