Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repository Pattern - How to understand it and how does it work with "complex" entities?

I'm having a hard time understanding the Repository Pattern.

There are a lot of opinions on that topic like in Repository pattern done right but also other stuff like Repository is the new Singleton or again like in Don't use DAO use Repository or just take Spring JPA Data + Hibernate + MySQL + MAVEN where somehow a Repository appears to be the same as a DAO object.

I'm getting tired of reading this stuff since imho this can't be such a hard thing as it is displayed in a lot of articles.

I see it like this: It appears that what I want is something like this:

         ------------------------------------------------------------------------          |                            Server                                    |          ------------------------------------------------------------------------          |                    |                        |                        | Client <-|-> Service Layer  <-|->  Repository Layer  <-|-> ORM / Database Layer |          |                    |                        |                        |            ------------------------------------------------------------------------ 

The Service Layer takes *DTOobjects and passes those to the Repository Layer that basically is nothing more than "the guy" who knows how an entity can be stored.

For example assume you have a composition of some tools (please note that this is just pseudo code)

@Entity class ToolSet {   @Id   public Long id;   @OneToOne   public Tool tool1;   @OneToOne   public Tool tool2; }  @Entity class Tool {   @Id   public Long id;   @OneToMany   public ToolDescription toolDescription; }  @Entity class ToolDescription {   @Id   public Long id;   @NotNull   @OneToOne   public Language language    public String name;   public String details; } 

The thing I'm not getting is the part where I am getting a ToolSetDTO object from the client.

As I understood it so far I could write a ToolSetRepository with a method ToolSetRepository.save(ToolSetDTO toolSetDto) that "knows how to store" a ToolSetDTO. But almost every tutorial does not pass the *DTO but the Entity instead.

What's bothering me here is that if you take my ToolSet example from above I'd have to do the following steps:

  1. Take toolSetDto and check if not null
  2. For each tool*Dto owned by toolSetDto
    a) If has a valid id then convert from DTO to Entity otherwise create a new database entry
    b) toolDescriptionDto and convert/save it to the database or create a new entry
  3. After checking those above instanciate ToolSet (entity) and set it up for persisting it in the database

All this is too complex to simply let the service function (interface for the client) handle this.

What I was thinking about was creating e.g. a ToolSetRepository but the question here is

  • Does it take a ToolSet entity object or does it use a DTO object?
  • In any case: Is the *Repository allowed to use other repository objects? Like when I want to save ToolSet but I have to store Tool and ToolDescription first - would I use ToolRepository and ToolDescriptionRepository inside ToolSetRepository?
    If so: Why doesn't it break the Repository Pattern? If this pattern is basically a layer between the service and my ORM framework it just does not "feel right" to add dependencies to other *Repository classes due to dependency reasons.

I don't know why I can't get my head around this. It does not sound that complicated but there's still help out there like Spring Data. Another thing that is bothering me since I really don't see how this makes anything easier. Especially since I'm using Hibernate already - I don't see the benefit (but maybe that's another question).

So .. I know this is a long question but I put already a few days of research into it. There's already existing code I am working on right now that starts to become a mess because I just can't see through this pattern.

I hope somebody can give me a bigger picture than most of the articles and tutorials which do not get beyond implementing a very, very simple example of a Repository Pattern.

like image 372
Stefan Falk Avatar asked Jul 08 '15 22:07

Stefan Falk


People also ask

How does repository pattern work?

The idea behind the Repository pattern is to decouple the data access layer from the business access layer of the application so that the operations (such as adding, updating, deleting, and selecting items from the collection) is done through straightforward methods without dealing with database concerns such as ...

What is entity repository pattern?

Repository Pattern is used to create an abstraction layer between data access layer and business logic layer of an application. Repository directly communicates with data access layer [DAL] and gets the data and provides it to business logic layer [BAL].

What problem does repository pattern solve?

They decouple application and domain design from persistence technology, multiple database strategies, or even multiple data sources.

What is the benefit of repository pattern in Entity Framework?

Benefits of Repository PatternIt centralizes data logic or business logic and service logic. It gives a substitution point for the unit tests. Provides a flexible architecture. If you want to modify the data access logic or business access logic, you don't need to change the repository logic.


1 Answers

You can read my "repository for dummies" post to understand the simple principle of the repository. I think your problem is that you're working with DTOs and in that scenario, you don't really use the repository pattern, you're using a DAO.

The main difference between a repository and a dao is that a repository returns only objects that are understood by the calling layer. Most of the time the repository is used by the business layer and thus, it returns business objects. A dao returns data which might or might not be a whole business object i.e the data isn't a valid business concept.

If your business objects are just data structures, it might be a hint you have a modeling problem i.e bad design. A repository makes more sense with 'rich' or at least properly encapsulated objects. If you're just loading/saving data structures probably you don't need a repository the orm is enough.

If you're dealing with business objects that are composed from other objects (an aggregate) and that object needs all its parts in order to be consistent (an aggregate root) then the repository pattern is the best solution because it will abstract all persistence details. Your app will just ask for a 'Product' and the repository will return it as a whole, regardless of how many tables or queries are required to restore the object.

Based on your code sample, you don't have 'real' business objects. You have data structures used by Hibernate. A business object is designed based on business concepts and use cases. The repository makes it possible for the BL not to care about how that object is persisted. In a way, a repository acts as a 'converter/mapper' between the object and the model that will be persisted. Basically the repo 'reduces' the objects to the required for persistence data.

A business object is not a ORM entity.It might be from a technical point of view, but from a design pov , one models business stuff the other models persistence stuff. In many cases these are not directly compatible.

The biggest mistake is to design your business object according to storage needs and mindset. And contrary to what many devs believe, an ORM purpose is not to persist business objects. Its purpose is to simulate a 'oop' database on top of a rdbms. The ORM mapping is between your db objects and tables, not between app objects (even less when dealing with business objects) and tables.

like image 159
MikeSW Avatar answered Sep 20 '22 17:09

MikeSW