Sự khác biệt giữa các mẫu DAO và Kho lưu trữ là gì?


423

Sự khác biệt giữa các mẫu Đối tượng truy cập dữ liệu (DAO) và các mẫu Kho lưu trữ là gì? Tôi đang phát triển một ứng dụng sử dụng Enterprise Java Beans (EJB3), Hibernate ORM làm cơ sở hạ tầng và Thiết kế hướng tên miền (DDD) và Phát triển dựa trên thử nghiệm (TDD) làm kỹ thuật thiết kế.

Câu trả lời:


471

DAOlà một sự trừu tượng của sự kiên trì dữ liệu .
Repositorylà một sự trừu tượng của một bộ sưu tập các đối tượng .

DAOsẽ được xem xét gần hơn với cơ sở dữ liệu, thường là trung tâm bảng.
Repositorysẽ được xem xét gần hơn với Miền, chỉ giao dịch trong Rễ tổng hợp.

Repositorycó thể được thực hiện bằng cách sử dụng DAO, nhưng bạn sẽ không làm điều ngược lại.

Ngoài ra, a Repositorythường là một giao diện hẹp hơn. Nó phải là chỉ đơn giản là một bộ sưu tập của các đối tượng, với một Get(id), Find(ISpecification), Add(Entity).

Một phương thức như Updatelà phù hợp trên một DAO, nhưng không phải là Repository- khi sử dụng a Repository, các thay đổi đối với các thực thể thường sẽ được theo dõi bởi UnitOfWork riêng biệt.

Có vẻ như thường thấy các triển khai được gọi là một Repositorythực sự nhiều hơn một DAO, và do đó tôi nghĩ có một số nhầm lẫn về sự khác biệt giữa chúng.


26
Chà, bạn sẽ không muốn lớp DAO của bạn thực hiện IRepositorygiao diện của bạn theo nghĩa đen . Bạn sẽ muốn kho lưu trữ của bạn sử dụng DAO trong triển khai. Hãy nhớ rằng, một DAO sẽ là một đối tượng trên mỗi bảng, trong khi Kho lưu trữ hầu như sẽ luôn phải sử dụng nhiều DAO để xây dựng một Thực thể duy nhất. Nếu bạn thấy đó không phải là trường hợp, thì Kho lưu trữ và Thực thể của bạn chỉ cần truy cập vào một bảng duy nhất, thì rất có thể bạn đang xây dựng một miền thiếu máu.
quentin-starin

29
Tôi đã nhận thấy trong thế giới .NET cụ thể là thuật ngữ "Kho lưu trữ" được sử dụng để chỉ những gì thực chất là một DAO; "DAO" là một thuật ngữ Java.
Wayne Molina

14
@Thurein DAO-s không phải trên mỗi bảng, mẫu chỉ trừu tượng hóa quyền truy cập vào dữ liệu của bạn - bạn có thể triển khai theo cách bạn muốn (mỗi bảng hoặc mỗi nhóm hoặc mô hình). Cách được đề xuất là luôn định hình DAO dựa trên mô hình miền của bạn thay vì kiên trì cơ bản vào tài khoản vì điều đó giúp sử dụng dễ dàng / rõ ràng hơn và giúp bạn linh hoạt hơn một chút về cách bạn duy trì nó (ví dụ: hãy tưởng tượng bạn sẽ cần một DAO lưu trữ dữ liệu của bạn trong các tệp XML hoặc lấy nó từ hàng đợi tin nhắn thay vì từ Cơ sở dữ liệu ...).
Stef

21
@Stef tôi không đồng ý. Một DAO trả về dữ liệu theo chính định nghĩa của nó (một đối tượng truy cập dữ liệu ). Một kho lưu trữ, theo định nghĩa của nó, trả về các đối tượng miền. Cần phải có lý do rằng kho lưu trữ sẽ sử dụng DAO chứ không phải theo cách khác, bởi vì trong OOP, chúng tôi kết hợp các đối tượng miền từ một hoặc nhiều đối tượng dữ liệu chứ không phải theo cách khác.
Mihai Danila

6
Tại sao Kho lưu trữ là khái niệm "Chỉ đọc" trong khi DAO là "Đọc và Viết"?
Dennis

120

OK, nghĩ rằng tôi có thể giải thích rõ hơn những gì tôi đã đưa vào bình luận :). Vì vậy, về cơ bản, bạn có thể thấy cả hai đều giống nhau, mặc dù DAO là một mẫu linh hoạt hơn so với Kho lưu trữ. Nếu bạn muốn sử dụng cả hai, bạn sẽ sử dụng Kho lưu trữ trong DAO-s của mình. Tôi sẽ giải thích từng người trong số họ dưới đây:

KHO:

Đây là kho lưu trữ của một loại đối tượng cụ thể - nó cho phép bạn tìm kiếm một loại đối tượng cụ thể cũng như lưu trữ chúng. Thông thường nó sẽ CHỈ xử lý một loại đối tượng. Ví dụ, AppleRepositorysẽ cho phép bạn làm AppleRepository.findAll(criteria)hoặc AppleRepository.save(juicyApple). Lưu ý rằng Kho lưu trữ đang sử dụng thuật ngữ Mô hình miền (không phải thuật ngữ DB - không có gì liên quan đến cách dữ liệu được duy trì ở bất cứ đâu).

Một kho lưu trữ rất có thể sẽ lưu trữ tất cả dữ liệu trong cùng một bảng, trong khi mẫu không yêu cầu điều đó. Thực tế là nó chỉ xử lý một loại dữ liệu, làm cho nó được kết nối hợp lý với một bảng chính (nếu được sử dụng để duy trì DB).

DAO - đối tượng truy cập dữ liệu (nói cách khác - đối tượng được sử dụng để truy cập dữ liệu)

DAO là một lớp định vị dữ liệu cho bạn (phần lớn là công cụ tìm, nhưng nó thường được sử dụng để lưu trữ dữ liệu). Mẫu không hạn chế bạn lưu trữ dữ liệu cùng loại, do đó bạn có thể dễ dàng có một DAO định vị / lưu trữ các đối tượng liên quan.

Ví dụ: bạn có thể dễ dàng có UserDao hiển thị các phương thức như

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

Tất cả những thứ đó có liên quan đến Người dùng (và bảo mật) và có thể được chỉ định theo cùng một DAO. Đây không phải là trường hợp cho Kho lưu trữ.

Cuối cùng

Lưu ý rằng cả hai mẫu thực sự có nghĩa giống nhau (chúng lưu trữ dữ liệu và chúng trừu tượng hóa quyền truy cập vào chúng và chúng đều được thể hiện gần hơn với mô hình miền và hầu như không chứa bất kỳ tham chiếu DB nào), nhưng cách chúng được sử dụng có thể hơi khác nhau, DAO linh hoạt / chung chung hơn một chút, trong khi Kho lưu trữ chỉ cụ thể hơn một chút và hạn chế đối với một loại.


Nếu tôi nhận được ví dụ như quyền này tôi có cái gì đó như CarDescriptioncó ví dụ language_idnhư chính nước ngoài - sau đó để lấy rằng tôi nên làm điều gì đó như thế này: CarRepository.getAll(new Criteria(carOwner.id, language.id));đó sẽ cho tôi tất cả những chiếc xe của một ngôn ngữ trong một ngôn ngữ cụ thể - đó là đúng cách để làm điều đó ?
hiển thị

@StefanFalk, hãy xem Spring Data, nó cho phép bạn thực hiện các cuộc gọi đẹp hơn thế nhiều. ví dụ: có thể được viết như thế CarRepository.findByLanguageId(language.id)và thậm chí bạn sẽ không cần phải viết mã, bạn chỉ cần xác định giao diện với một phương thức có tên đó và Spring Data đảm nhiệm việc xây dựng triển khai lớp mặc định cho bạn. Công cụ khá gọn gàng;)
Stef

2
Cái hay của Spring Data là bạn không thực sự phải viết các truy vấn, bạn chỉ cần tạo một giao diện (giống như TodoRep repository trong ví dụ của bạn, có phương thức này findById). Và bạn thực tế được thực hiện. Spring Data làm gì, nó tìm thấy tất cả các giao diện mà bạn đã tạo để mở rộng giao diện Kho lưu trữ và tạo các lớp cho bạn. Bạn sẽ không bao giờ thấy các lớp đó và bạn sẽ không thể tạo các thể hiện mới, nhưng bạn không cần vì bạn chỉ có thể tự động kích hoạt giao diện và để Spring định vị đối tượng kho lưu trữ đó.
Stef

1
Cuối cùng, bạn không phải sử dụng Spring Data, bạn có thể tự viết theo cách cũ để viết các phương thức truy vấn (sử dụng API tiêu chí, v.v.), nhưng bạn sẽ khiến cuộc sống của mình phức tạp hơn một chút ... Bạn có thể nói rằng bạn sẽ linh hoạt hơn như thế, nhưng điều đó không đúng vì nếu bạn thực sự muốn phát điên với các truy vấn của mình, Spring Data cho phép bạn thực hiện hai cách: chú thích @Query hoặc nếu điều đó không hiệu quả, bạn có thể tạo các kho lưu trữ tùy chỉnh là một tiện ích mở rộng mang lại cho bạn sức mạnh tương tự như khi bạn viết bản thực hiện của riêng mình từ đầu.
Bắt đầu

2
"Tổng hợp gốc" là một thuật ngữ thường được kết nối với mẫu kho lưu trữ. Tôi không biết làm thế nào bạn sẽ sử dụng điều đó với định nghĩa của bạn về một kho lưu trữ.
Christian Strempfer

90

Mẫu DAO và Kho lưu trữ là cách triển khai Lớp truy cập dữ liệu (DAL). Vì vậy, trước tiên hãy bắt đầu với DAL.

Các ứng dụng hướng đối tượng truy cập cơ sở dữ liệu, phải có một số logic để xử lý truy cập cơ sở dữ liệu. Để giữ cho mã sạch và mô-đun, nên tách biệt logic truy cập cơ sở dữ liệu vào một mô-đun riêng biệt. Trong kiến ​​trúc lớp, mô-đun này là DAL.

Cho đến nay, chúng ta chưa nói về bất kỳ triển khai cụ thể nào: chỉ có một nguyên tắc chung là đưa logic truy cập cơ sở dữ liệu vào một mô-đun riêng biệt.

Bây giờ, làm thế nào chúng ta có thể thực hiện nguyên tắc này? Chà, một cách biết để thực hiện điều này, đặc biệt với các khung như Hibernate, là mẫu DAO.

Mẫu DAO là một cách tạo DAL, thông thường, mỗi thực thể miền có DAO riêng. Ví dụ, UserUserDao, AppointmentAppointmentDaovv Một ví dụ về DAO với Hibernate: http://gochev.blogspot.ca/2009/08/hibernate-generic-dao.html .

Vậy thì mô hình Kho lưu trữ là gì? Giống như DAO, mẫu Kho lưu trữ cũng là một cách để đạt được DAL. Điểm chính trong mẫu Kho lưu trữ là, từ góc độ máy khách / người dùng, nó sẽ trông hoặc hoạt động như một bộ sưu tập. Điều gì có nghĩa là bằng cách cư xử như một bộ sưu tập không phải là nó phải được khởi tạo như thế nào Collection collection = new SomeCollection(). Thay vào đó, nó có nghĩa là nó nên hỗ trợ các hoạt động như thêm, xóa, chứa, v.v ... Đây là bản chất của mẫu Kho lưu trữ.

Trong thực tế, ví dụ trong trường hợp sử dụng Hibernate, mẫu Kho lưu trữ được hiện thực hóa bằng DAO. Đó là một thể hiện của DAL có thể là cùng một thể hiện của mẫu DAO và mẫu Kho lưu trữ.

Mẫu lưu trữ không nhất thiết phải là thứ mà người ta xây dựng trên DAO (như một số có thể đề xuất). Nếu các DAO được thiết kế với giao diện hỗ trợ các hoạt động được đề cập ở trên, thì đó là một thể hiện của mẫu Kho lưu trữ. Hãy suy nghĩ về điều này, nếu các DAO đã cung cấp một tập hợp các thao tác giống như bộ sưu tập, vậy thì cần thêm một lớp bổ sung nào ở trên nó?


5
"Nếu các DAO đã cung cấp một tập hợp các thao tác giống như bộ sưu tập, vậy thì cần thêm một lớp bổ sung nào ở trên nó?" Giả sử bạn đang lập mô hình cửa hàng thú cưng và bạn có một bảng 'PetType' với các động vật khác nhau và thuộc tính của chúng (tên: "Cat", loại: "Động vật có vú", v.v.) được tham chiếu bởi một bảng 'Pet' của vật nuôi cụ thể mà bạn có trong cửa hàng (tên: "Katniss", giống: "Calico", v.v.). Nếu bạn muốn thêm một loại động vật chưa có trong cơ sở dữ liệu, bạn có thể sử dụng kho lưu trữ để nhóm hai cuộc gọi DAO riêng biệt (một để tạo PetType và một cho Pet) trong một phương thức, tránh ghép nối trong DAO
Matt

1
Lời giải thích tuyệt vời, thưa ngài!
Paul-Sebastian Manole

74

Thành thật mà nói, điều này trông giống như một sự phân biệt ngữ nghĩa, không phải là một sự phân biệt kỹ thuật. Cụm từ Đối tượng truy cập dữ liệu hoàn toàn không đề cập đến "cơ sở dữ liệu". Và, mặc dù bạn có thể thiết kế nó thành trung tâm cơ sở dữ liệu, tôi nghĩ rằng hầu hết mọi người sẽ coi đó là một lỗ hổng thiết kế.

Mục đích của DAO là ẩn các chi tiết triển khai của cơ chế truy cập dữ liệu. Mẫu Kho lưu trữ khác nhau như thế nào? Theo như tôi có thể nói, thì không. Nói một Kho lưu trữ khác với DAO vì bạn đang xử lý / trả lại một bộ sưu tập các đối tượng không thể đúng; DAO cũng có thể trả về bộ sưu tập các đối tượng.

Mọi thứ tôi đã đọc về mẫu kho lưu trữ dường như đều dựa vào sự khác biệt này: thiết kế DAO xấu so với thiết kế DAO tốt (hay còn gọi là mẫu thiết kế kho lưu trữ).


5
vâng, hoàn toàn đồng ý, về cơ bản chúng giống nhau. DAO âm thanh liên quan đến DB nhiều hơn, nhưng nó không phải. Giống như Kho lưu trữ, nó chỉ là một bản tóm tắt được sử dụng để ẩn vị trí và cách dữ liệu được đặt.
Stef

+1 Đối với tuyên bố này. Thành thật mà nói, điều này trông giống như một sự phân biệt ngữ nghĩa, không phải là một sự phân biệt kỹ thuật. Cụm từ Đối tượng truy cập dữ liệu hoàn toàn không đề cập đến "cơ sở dữ liệu".
Sudhakar Chavali

1
Điểm khi so sánh các kho lưu trữ và các bộ sưu tập không phải là chúng đang xử lý / trả lại các bộ sưu tập của các đối tượng, mà là các kho lưu trữ hoạt động như thể chúng là các bộ sưu tập. Chẳng hạn, trong Java có nghĩa là Kho lưu trữ không có phương thức cập nhật vì khi bạn sửa đổi một đối tượng trong bộ sưu tập, nó sẽ được cập nhật tự động (vì các bộ sưu tập Java chỉ lưu trữ các tham chiếu đến các đối tượng).
Christoph Böhme

17

Kho lưu trữ là thuật ngữ định hướng miền trừu tượng hơn, là một phần của Thiết kế hướng miền, nó là một phần của thiết kế miền của bạn và là ngôn ngữ chung, DAO là một bản tóm tắt kỹ thuật cho công nghệ truy cập dữ liệu, kho lưu trữ chỉ quan tâm đến việc quản lý dữ liệu và nhà máy hiện có để tạo dữ liệu.

kiểm tra các liên kết sau:

http://warren.mayocchi.com/2006/07/27/reposeective-or-dao/ http://fabiomaulo.blogspot.com/2009/09/reposeective-or-dao-reposeective.html


6

Sự khác biệt chính là kho lưu trữ xử lý quyền truy cập vào các gốc tổng hợp trong một tổng hợp, trong khi DAO xử lý quyền truy cập vào các thực thể. Do đó, thông thường là một kho lưu trữ ủy thác sự tồn tại thực tế của các gốc tổng hợp cho một DAO. Ngoài ra, vì gốc tổng hợp phải xử lý quyền truy cập của các thực thể khác, nên có thể cần ủy quyền quyền truy cập này cho các DAO khác.


5

DAO cung cấp sự trừu tượng hóa trên các tệp cơ sở dữ liệu / dữ liệu hoặc bất kỳ cơ chế lưu giữ lâu bền nào khác để lớp có thể được thao tác mà không cần biết chi tiết triển khai.

Trong khi đó trong các lớp Kho lưu trữ, nhiều lớp DAO có thể được sử dụng trong một phương thức Kho lưu trữ duy nhất để thực hiện một thao tác từ "phối cảnh ứng dụng". Vì vậy, thay vì sử dụng nhiều DAO ở lớp Miền, hãy sử dụng kho lưu trữ để hoàn thành nó. Kho lưu trữ là lớp có thể chứa một số logic ứng dụng như: Nếu dữ liệu có sẵn trong bộ nhớ cache trong bộ nhớ thì hãy lấy nó từ bộ đệm, nếu không, hãy lấy dữ liệu từ mạng và lưu trữ trong bộ nhớ cache trong bộ nhớ để truy xuất lần sau.


3

Kho lưu trữ không có gì ngoài DAO được thiết kế tốt.

ORM là bảng trung tâm nhưng không phải DAO.

Không cần sử dụng nhiều DAO trong kho lưu trữ vì bản thân DAO có thể làm chính xác như vậy với kho / thực thể ORM hoặc bất kỳ nhà cung cấp DAL nào, bất kể xe ở đâu và như thế nào vẫn tồn tại 1 bảng, 2 bảng, n bảng, nửa bảng, một bảng dịch vụ web, bảng và dịch vụ web, vv Các dịch vụ sử dụng một số kho / DAO.

DAO của riêng tôi, giả sử CarDao chỉ giao dịch với Car DTO, ý tôi là, chỉ lấy Car DTO trong đầu vào và chỉ trả lại bộ sưu tập DTO cho xe hoặc DTO cho xe.

Vì vậy, giống như Kho lưu trữ, DAO thực sự là một IoC, đối với logic kinh doanh, cho phép các giao diện kiên trì không bị đe dọa bởi các chiến lược hoặc di sản liên tục. DAO cả hai gói gọn chiến lược bền bỉ và không cung cấp giao diện kiên trì liên quan đến tên miền. Kho lưu trữ chỉ là một từ khác cho những người chưa hiểu thực tế DAO được xác định rõ là gì.


Trước hết "kho / thực thể ORM"? Bạn có nghĩa là các thực thể ORM. Không có thứ gọi là kho lưu trữ ORM. Thứ hai trong số các ORM thường chỉ giao dịch với các thực thể, tức là. mô hình miền. DAO xử lý các bảng trực tiếp và truy cập dữ liệu trừu tượng. Họ trả lại các thực thể là tốt. Các kho lưu trữ là sự trừu tượng cao nhất, cung cấp một giao diện thu thập để nhận các thực thể. Một DAO có thể là một kho lưu trữ, tức là. trừu tượng hóa công cụ lưu trữ thực tế, cung cấp giao diện cho nó và cũng cung cấp chế độ xem bộ sưu tập các thực thể (bộ đệm). Một DAO có thể sử dụng ORM để giao tiếp với cơ sở dữ liệu và ủy quyền cho các thực thể ops.
Paul-Sebastian Manole

3
Đồng ý với @brokenthorn. Điểm quan trọng nhất trong nhận xét của ông là "Kho lưu trữ là sự trừu tượng hóa cao nhất" và sự trừu tượng hóa này trở thành một điều cần thiết khi bạn muốn bảo vệ mã miền của mình khỏi công nghệ cơ sở dữ liệu cơ bản. Các khái niệm Trình điều khiển ORM / Adaptor / DB có xu hướng rò rỉ vào DAO. Nếu bạn có một ứng dụng hỗ trợ nhiều công nghệ cơ sở dữ liệu hoặc nếu bạn muốn ứng dụng của mình không bị khóa với cơ sở dữ liệu, sử dụng DAO trực tiếp từ mô hình miền là điều không nên.
Subhash Bhushan

2

Hãy thử tìm hiểu xem DAO hoặc mẫu Kho lưu trữ có thể áp dụng nhất cho tình huống sau: Hãy tưởng tượng bạn muốn cung cấp API truy cập dữ liệu thống nhất cho một cơ chế bền vững cho các loại nguồn dữ liệu khác nhau như RDBMS, LDAP, OODB, kho lưu trữ XML và các tập tin phẳng.

Cũng tham khảo các liên kết sau đây, nếu quan tâm:

http://www.codeinsanity.com/2008/08/reposeective-potype.html

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

http://devlicio.us/bloss/casey/archive/2009/02/20/ddd-the-reposeective-potype.aspx

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

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


0

trong một câu rất đơn giản: Sự khác biệt đáng kể là Kho lưu trữ đại diện cho các bộ sưu tập, trong khi các DAO gần với cơ sở dữ liệu hơn, thường là trung tâm bảng hơn nhiều.


DAO cũng có thể đại diện cho các bộ sưu tập / đối tượng ...
Yousha Aleayoub

0

Trong khung mùa xuân, có một chú thích được gọi là kho lưu trữ, và trong phần mô tả của chú thích này, có thông tin hữu ích về kho lưu trữ, mà tôi nghĩ nó hữu ích cho cuộc thảo luận này.

Chỉ ra rằng một lớp chú thích là một "Kho lưu trữ", ban đầu được xác định bởi Thiết kế hướng tên miền (Evans, 2003) là "một cơ chế để đóng gói lưu trữ, truy xuất và hành vi tìm kiếm mô phỏng một bộ sưu tập các đối tượng".

Các nhóm triển khai các mẫu Java EE truyền thống như "Đối tượng truy cập dữ liệu" cũng có thể áp dụng bản mẫu này cho các lớp DAO, tuy nhiên cần chú ý để phân biệt giữa kho lưu trữ đối tượng truy cập dữ liệu và kho lưu trữ kiểu DDD trước khi thực hiện. Chú thích này là một bản mẫu có mục đích chung và các nhóm riêng lẻ có thể thu hẹp ngữ nghĩa của họ và sử dụng khi thích hợp.

Do đó, một lớp được chú thích đủ điều kiện cho bản dịch Spring DataAccessException khi được sử dụng cùng với một PersistenceExceptionTranslationPostProcessor. Lớp chú thích cũng được làm rõ về vai trò của nó trong kiến ​​trúc ứng dụng tổng thể cho mục đích công cụ, các khía cạnh, v.v.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.